diff options
Diffstat (limited to 'tests')
56 files changed, 1667 insertions, 410 deletions
diff --git a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp index 32344f1e26..1b7d410beb 100644 --- a/tests/auto/corelib/io/qdebug/tst_qdebug.cpp +++ b/tests/auto/corelib/io/qdebug/tst_qdebug.cpp @@ -49,6 +49,7 @@ private slots: void debugWithBool() const; void debugSpaceHandling() const; void debugNoQuotes() const; + void verbosity() const; void stateSaver() const; void veryLongWarningMessage() const; void qDebugQChar() const; @@ -192,7 +193,11 @@ public: QDebug operator<< (QDebug s, const MyLine& line) { const QDebugStateSaver saver(s); - s.nospace() << "MyLine(" << line.p1 << ", " << line.p2 << ")"; + s.nospace(); + s << "MyLine(" << line.p1 << ", "<< line.p2; + if (s.verbosity() > 2) + s << ", Manhattan length=" << (qAbs(line.p2.v1 - line.p1.v1) + qAbs(line.p2.v2 - line.p1.v2)); + s << ')'; return s; } @@ -255,6 +260,33 @@ void tst_QDebug::debugNoQuotes() const QCOMPARE(s_msg, QString::fromLatin1("'H' \"Hello\" \"Hello\" H Hello Hello")); } +void tst_QDebug::verbosity() const +{ + MyLine line(MyPoint(10, 11), MyPoint (12, 13)); + QString output; + QDebug d(&output); + d.nospace(); + d << line << '\n'; + const int oldVerbosity = d.verbosity(); + d.setVerbosity(0); + QCOMPARE(d.verbosity(), 0); + d.setVerbosity(7); + QCOMPARE(d.verbosity(), 7); + const int newVerbosity = oldVerbosity + 2; + d.setVerbosity(newVerbosity); + QCOMPARE(d.verbosity(), newVerbosity); + d << line << '\n'; + d.setVerbosity(oldVerbosity ); + QCOMPARE(d.verbosity(), oldVerbosity ); + d << line; + const QStringList lines = output.split(QLatin1Char('\n')); + QCOMPARE(lines.size(), 3); + // Verbose should be longer + QVERIFY2(lines.at(1).size() > lines.at(0).size(), qPrintable(lines.join(QLatin1Char(',')))); + // Switching back to brief produces same output + QCOMPARE(lines.at(0).size(), lines.at(2).size()); +} + void tst_QDebug::stateSaver() const { MessageHandlerSetter mhs(myMessageHandler); diff --git a/tests/auto/corelib/io/qfileselector/platforms/+haiku/test b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test diff --git a/tests/auto/corelib/io/qfileselector/platforms/+haiku/test2 b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test2 new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/corelib/io/qfileselector/platforms/+haiku/test2 diff --git a/tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test b/tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/tests/auto/corelib/io/qfileselector/platforms/+unix/+haiku/test diff --git a/tests/auto/corelib/io/qfileselector/qfileselector.qrc b/tests/auto/corelib/io/qfileselector/qfileselector.qrc index 661647f933..6e2699774d 100644 --- a/tests/auto/corelib/io/qfileselector/qfileselector.qrc +++ b/tests/auto/corelib/io/qfileselector/qfileselector.qrc @@ -19,6 +19,7 @@ <file>platforms/+unix/+darwin/+mac/+osx/test</file> <file>platforms/+unix/+darwin/+mac/test</file> <file>platforms/+unix/+darwin/test</file> + <file>platforms/+unix/+haiku/test</file> <file>platforms/+unix/+linux/test</file> <file>platforms/+unix/test</file> <file>platforms/+windows/+wince/test</file> @@ -30,6 +31,7 @@ <file>platforms/+osx/test</file> <file>platforms/+darwin/test</file> <file>platforms/+mac/test</file> + <file>platforms/+haiku/test</file> <file>platforms/+linux/test</file> <file>platforms/+wince/test</file> @@ -39,6 +41,7 @@ <file>platforms/+blackberry/test2</file> <file>platforms/+ios/test2</file> <file>platforms/+osx/test2</file> + <file>platforms/+haiku/test2</file> <file>platforms/+linux/test2</file> <file>platforms/+wince/test2</file> <file>platforms/+winnt/test2</file> diff --git a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp index b3767b4887..87381f4c4e 100644 --- a/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp +++ b/tests/auto/corelib/io/qfileselector/tst_qfileselector.cpp @@ -89,7 +89,7 @@ void tst_QFileSelector::basicTest_data() QString expectedPlatform2File(""); //Only the last selector QString expectedPlatform3File; // Only the first selector (the family) #if defined(Q_OS_UNIX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_BLACKBERRY) && \ - !defined(Q_OS_DARWIN) && !defined(Q_OS_LINUX) + !defined(Q_OS_DARWIN) && !defined(Q_OS_LINUX) && !defined(Q_OS_HAIKU) /* We are only aware of specific unixes, and do not have test files for any of the others. However those unixes can get a selector added from the result of a uname call, so this will lead to a case where we don't have that file so we can't expect the concatenation of platform diff --git a/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp b/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp index db0136dd20..769a96ac64 100644 --- a/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp +++ b/tests/auto/corelib/io/qurlquery/tst_qurlquery.cpp @@ -177,6 +177,7 @@ void tst_QUrlQuery::constructing() QVERIFY(copy.isEmpty()); QVERIFY(!copy.isDetached()); QVERIFY(copy == empty); + QCOMPARE(qHash(copy), qHash(empty)); QVERIFY(!(copy != empty)); copy = empty; @@ -184,6 +185,7 @@ void tst_QUrlQuery::constructing() copy = QUrlQuery(); QVERIFY(copy == empty); + QCOMPARE(qHash(copy), qHash(empty)); } { QUrlQuery copy(emptyQuery()); @@ -298,6 +300,7 @@ void tst_QUrlQuery::addRemove() QVERIFY(query == original); QVERIFY(!(query != original)); + QCOMPARE(qHash(query), qHash(original)); } { diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index a192ccde59..6da8f55e61 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -3357,9 +3357,6 @@ void tst_QVariant::numericalConvert_data() void tst_QVariant::numericalConvert() { -#if defined(Q_OS_LINUX) && defined(Q_CC_GNU) && !defined(__x86_64__) - QSKIP("Known to fail due to a GCC bug on at least Ubuntu 10.04 32-bit - check QTBUG-8959"); -#endif QFETCH(QVariant, v); QFETCH(bool, isInteger); double num = isInteger ? 5 : 5.3; diff --git a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp index bdbb291d7f..cd77b188cc 100644 --- a/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp +++ b/tests/auto/corelib/plugin/qpluginloader/tst_qpluginloader.cpp @@ -120,6 +120,7 @@ private slots: void loadGarbage(); #endif void relativePath(); + void absolutePath(); void reloadPlugin(); void preloadedPlugin_data(); void preloadedPlugin(); @@ -406,6 +407,20 @@ void tst_QPluginLoader::relativePath() QVERIFY(loader.unload()); } +void tst_QPluginLoader::absolutePath() +{ + // Windows binaries run from release and debug subdirs, so we can't rely on the current dir. + const QString binDir = QFINDTESTDATA("bin"); + QVERIFY(!binDir.isEmpty()); + QVERIFY(QDir::isAbsolutePath(binDir)); + QPluginLoader loader(binDir + "/theplugin"); + loader.load(); // not recommended, instance() should do the job. + PluginInterface *instance = qobject_cast<PluginInterface*>(loader.instance()); + QVERIFY(instance); + QCOMPARE(instance->pluginName(), QLatin1String("Plugin ok")); + QVERIFY(loader.unload()); +} + void tst_QPluginLoader::reloadPlugin() { QPluginLoader loader; diff --git a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp index 9bce948140..99e5c4c85d 100644..100755 --- a/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp +++ b/tests/auto/corelib/tools/qalgorithms/tst_qalgorithms.cpp @@ -31,6 +31,7 @@ ** ****************************************************************************/ +#include "../../../../../src/corelib/tools/qalgorithms.h" #include <QtTest/QtTest> #include <iostream> @@ -80,6 +81,24 @@ private slots: void popCount32() { popCount_impl<quint32>(); } void popCount64() { popCount_impl<quint64>(); } + void countTrailing08_data() { countTrailing_data_impl(sizeof(quint8 )); } + void countTrailing16_data() { countTrailing_data_impl(sizeof(quint16)); } + void countTrailing32_data() { countTrailing_data_impl(sizeof(quint32)); } + void countTrailing64_data() { countTrailing_data_impl(sizeof(quint64)); } + void countTrailing08() { countTrailing_impl<quint8 >(); } + void countTrailing16() { countTrailing_impl<quint16>(); } + void countTrailing32() { countTrailing_impl<quint32>(); } + void countTrailing64() { countTrailing_impl<quint64>(); } + + void countLeading08_data() { countLeading_data_impl(sizeof(quint8 )); } + void countLeading16_data() { countLeading_data_impl(sizeof(quint16)); } + void countLeading32_data() { countLeading_data_impl(sizeof(quint32)); } + void countLeading64_data() { countLeading_data_impl(sizeof(quint64)); } + void countLeading08() { countLeading_impl<quint8 >(); } + void countLeading16() { countLeading_impl<quint16>(); } + void countLeading32() { countLeading_impl<quint32>(); } + void countLeading64() { countLeading_impl<quint64>(); } + private: #if Q_TEST_PERFORMANCE void performance(); @@ -87,6 +106,14 @@ private: void popCount_data_impl(size_t sizeof_T_Int); template <typename T_Int> void popCount_impl(); + + void countTrailing_data_impl(size_t sizeof_T_Int); + template <typename T_Int> + void countTrailing_impl(); + + void countLeading_data_impl(size_t sizeof_T_Int); + template <typename T_Int> + void countLeading_impl(); }; class TestInt @@ -1084,6 +1111,86 @@ void tst_QAlgorithms::popCount_impl() QCOMPARE(qPopulationCount(value), expected); } +void tst_QAlgorithms::countTrailing_data_impl(size_t sizeof_T_Int) +{ + using namespace QTest; + addColumn<quint64>("input"); + addColumn<uint>("expected"); + + int nibs = sizeof_T_Int*2; + + newRow(("0x"+QByteArray::number(0,16).rightJustified(nibs,'0')).constData()) << Q_UINT64_C(0) << uint(sizeof_T_Int*8); + for (uint i = 0; i < sizeof_T_Int*8; ++i) { + const quint64 input = Q_UINT64_C(1) << i; + newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << i; + } + + quint64 type_mask; + if (sizeof_T_Int>=8) + type_mask = ~Q_UINT64_C(0); + else + type_mask = (Q_UINT64_C(1) << (sizeof_T_Int*8))-1; + + // and some random ones: + for (uint i = 0; i < sizeof_T_Int*8; ++i) { + for (uint j = 0; j < sizeof_T_Int*3; ++j) { // 3 is arbitrary + const quint64 r = quint64(qrand()) << 32 | quint32(qrand()); + const quint64 b = Q_UINT64_C(1) << i; + const quint64 mask = ((~(b-1)) ^ b) & type_mask; + const quint64 input = (r&mask) | b; + newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << i; + } + } +} + +template <typename T_Int> +void tst_QAlgorithms::countTrailing_impl() +{ + QFETCH(quint64, input); + QFETCH(uint, expected); + + const T_Int value = static_cast<T_Int>(input); + + QCOMPARE(qCountTrailingZeroBits(value), expected); +} + +void tst_QAlgorithms::countLeading_data_impl(size_t sizeof_T_Int) +{ + using namespace QTest; + addColumn<quint64>("input"); + addColumn<uint>("expected"); + + int nibs = sizeof_T_Int*2; + + newRow(("0x"+QByteArray::number(0,16).rightJustified(nibs,'0')).constData()) << Q_UINT64_C(0) << uint(sizeof_T_Int*8); + for (uint i = 0; i < sizeof_T_Int*8; ++i) { + const quint64 input = Q_UINT64_C(1) << i; + newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << uint(sizeof_T_Int*8-i-1); + } + + // and some random ones: + for (uint i = 0; i < sizeof_T_Int*8; ++i) { + for (uint j = 0; j < sizeof_T_Int*3; ++j) { // 3 is arbitrary + const quint64 r = quint64(qrand()) << 32 | quint32(qrand()); + const quint64 b = Q_UINT64_C(1) << i; + const quint64 mask = b-1; + const quint64 input = (r&mask) | b; + newRow(("0x"+QByteArray::number(input,16).rightJustified(nibs,'0')).constData()) << input << uint(sizeof_T_Int*8-i-1); + } + } +} + +template <typename T_Int> +void tst_QAlgorithms::countLeading_impl() +{ + QFETCH(quint64, input); + QFETCH(uint, expected); + + const T_Int value = static_cast<T_Int>(input); + + QCOMPARE(qCountLeadingZeroBits(value), expected); +} + QTEST_APPLESS_MAIN(tst_QAlgorithms) #include "tst_qalgorithms.moc" diff --git a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp index 7b1b7ce963..6e09ebb09b 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/testhelper/qcommandlineparser_test_helper.cpp @@ -73,6 +73,12 @@ int main(int argc, char *argv[]) "abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz")); parser.addOption(newlineOption); + // A hidden option + QCommandLineOption hiddenOption(QStringList() << QStringLiteral("hidden")); + hiddenOption.setDescription(QStringLiteral("THIS SHOULD NEVER APPEAR")); + hiddenOption.setHidden(true); + parser.addOption(hiddenOption); + // This program supports different options depending on the "command" (first argument). // Call parse() to find out the positional arguments. parser.parse(QCoreApplication::arguments()); diff --git a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp index 6ff46ed20b..9c4ded69de 100644 --- a/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp +++ b/tests/auto/corelib/tools/qcommandlineparser/tst_qcommandlineparser.cpp @@ -35,6 +35,7 @@ #include <QtCore/QCommandLineParser> Q_DECLARE_METATYPE(char**) +Q_DECLARE_METATYPE(QCommandLineParser::OptionsAfterPositionalArgumentsMode) class tst_QCommandLineParser : public QObject { @@ -51,6 +52,8 @@ private slots: void testPositionalArguments(); void testBooleanOption_data(); void testBooleanOption(); + void testOptionsAndPositional_data(); + void testOptionsAndPositional(); void testMultipleNames_data(); void testMultipleNames(); void testSingleValueOption_data(); @@ -141,6 +144,40 @@ void tst_QCommandLineParser::testBooleanOption() QVERIFY(!parser.isSet("c")); } +void tst_QCommandLineParser::testOptionsAndPositional_data() +{ + QTest::addColumn<QStringList>("args"); + QTest::addColumn<QStringList>("expectedOptionNames"); + QTest::addColumn<bool>("expectedIsSet"); + QTest::addColumn<QStringList>("expectedPositionalArguments"); + QTest::addColumn<QCommandLineParser::OptionsAfterPositionalArgumentsMode>("parsingMode"); + + const QStringList arg = QStringList() << "arg"; + QTest::newRow("before_positional_default") << (QStringList() << "tst_qcommandlineparser" << "-b" << "arg") << (QStringList() << "b") << true << arg << QCommandLineParser::ParseAsOptions; + QTest::newRow("after_positional_default") << (QStringList() << "tst_qcommandlineparser" << "arg" << "-b") << (QStringList() << "b") << true << arg << QCommandLineParser::ParseAsOptions; + QTest::newRow("before_positional_parseAsArg") << (QStringList() << "tst_qcommandlineparser" << "-b" << "arg") << (QStringList() << "b") << true << arg << QCommandLineParser::ParseAsPositionalArguments; + QTest::newRow("after_positional_parseAsArg") << (QStringList() << "tst_qcommandlineparser" << "arg" << "-b") << (QStringList()) << false << (QStringList() << "arg" << "-b") << QCommandLineParser::ParseAsPositionalArguments; +} + +void tst_QCommandLineParser::testOptionsAndPositional() +{ + QFETCH(QStringList, args); + QFETCH(QStringList, expectedOptionNames); + QFETCH(bool, expectedIsSet); + QFETCH(QStringList, expectedPositionalArguments); + QFETCH(QCommandLineParser::OptionsAfterPositionalArgumentsMode, parsingMode); + + QCoreApplication app(empty_argc, empty_argv); + QCommandLineParser parser; + parser.setOptionsAfterPositionalArgumentsMode(parsingMode); + QVERIFY(parser.addOption(QCommandLineOption(QStringLiteral("b"), QStringLiteral("a boolean option")))); + QVERIFY(parser.parse(args)); + QCOMPARE(parser.optionNames(), expectedOptionNames); + QCOMPARE(parser.isSet("b"), expectedIsSet); + QCOMPARE(parser.values("b"), QStringList()); + QCOMPARE(parser.positionalArguments(), expectedPositionalArguments); +} + void tst_QCommandLineParser::testMultipleNames_data() { QTest::addColumn<QStringList>("args"); diff --git a/tests/auto/corelib/tools/qlist/tst_qlist.cpp b/tests/auto/corelib/tools/qlist/tst_qlist.cpp index 1207986dde..dd9371fbe1 100644 --- a/tests/auto/corelib/tools/qlist/tst_qlist.cpp +++ b/tests/auto/corelib/tools/qlist/tst_qlist.cpp @@ -76,6 +76,13 @@ struct Movable { return i == other.i; } + bool operator<(const Movable &other) const + { + check(state, Constructed); + check(other.state, Constructed); + return i < other.i; + } + Movable &operator=(const Movable &other) { check(state, Constructed); @@ -144,6 +151,13 @@ struct Optimal return i == other.i; } + bool operator<(const Optimal &other) const + { + check(state, Constructed); + check(other.state, Constructed); + return i < other.i; + } + Optimal &operator=(const Optimal &other) { check(state, Constructed); @@ -220,6 +234,12 @@ struct Complex return value == other.value; } + bool operator<(Complex const &other) const + { + check(); other.check(); + return value < other.value; + } + void check() const { QVERIFY(this == checkSum); @@ -329,6 +349,9 @@ private slots: void replaceOptimal() const; void replaceMovable() const; void replaceComplex() const; + void reverseIteratorsOptimal() const; + void reverseIteratorsMovable() const; + void reverseIteratorsComplex() const; void startsWithOptimal() const; void startsWithMovable() const; void startsWithComplex() const; @@ -376,6 +399,9 @@ private slots: void eraseValidIteratorsOnSharedList() const; void insertWithValidIteratorsOnSharedList() const; + void qhashOptimal() const { qhash<Optimal>(); } + void qhashMovable() const { qhash<Movable>(); } + void qhashComplex() const { qhash<Complex>(); } void reserve() const; private: template<typename T> void length() const; @@ -392,10 +418,12 @@ private: template<typename T> void endsWith() const; template<typename T> void lastIndexOf() const; template<typename T> void move() const; + template<typename T> void qhash() const; template<typename T> void removeAll() const; template<typename T> void removeAt() const; template<typename T> void removeOne() const; template<typename T> void replace() const; + template<typename T> void reverseIterators() const; template<typename T> void startsWith() const; template<typename T> void swap() const; template<typename T> void takeAt() const; @@ -1220,6 +1248,43 @@ void tst_QList::replaceComplex() const } template<typename T> +void tst_QList::reverseIterators() const +{ + QList<T> v; + v << T_CAT << T_DOG << T_BLAH << T_BAZ; + QList<T> vr = v; + std::reverse(vr.begin(), vr.end()); + const QList<T> &cvr = vr; + QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin())); + QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin())); + QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin())); + QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin())); + QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin())); + QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin())); +} + +void tst_QList::reverseIteratorsOptimal() const +{ + const int liveCount = Optimal::getLiveCount(); + reverseIterators<Optimal>(); + QCOMPARE(liveCount, Optimal::getLiveCount()); +} + +void tst_QList::reverseIteratorsMovable() const +{ + const int liveCount = Movable::getLiveCount(); + reverseIterators<Movable>(); + QCOMPARE(liveCount, Movable::getLiveCount()); +} + +void tst_QList::reverseIteratorsComplex() const +{ + const int liveCount = Complex::getLiveCount(); + reverseIterators<Complex>(); + QCOMPARE(liveCount, Complex::getLiveCount()); +} + +template<typename T> void tst_QList::startsWith() const { QList<T> list; @@ -1576,6 +1641,19 @@ void tst_QList::testOperators() const // [] QCOMPARE(list[0], T_FOO); QCOMPARE(list[list.size() - 1], T_CAT); + + // <, >, <=, >= + QVERIFY(!(list < listtwo)); + QVERIFY(!(list > listtwo)); + QVERIFY( list <= listtwo); + QVERIFY( list >= listtwo); + listtwo.push_back(T_CAT); + QVERIFY( list < listtwo); + QVERIFY(!(list > listtwo)); + QVERIFY( list <= listtwo); + QVERIFY(!(list >= listtwo)); + QVERIFY(listtwo > list); + QVERIFY(listtwo >= list); } void tst_QList::testOperatorsOptimal() const @@ -1834,6 +1912,16 @@ void tst_QList::insertWithValidIteratorsOnSharedList() const QCOMPARE(a.at(1), 15); } +template <typename T> +void tst_QList::qhash() const +{ + QList<T> l1, l2; + QCOMPARE(qHash(l1), qHash(l2)); + l1 << T_BAR; + l2 << T_BAR; + QCOMPARE(qHash(l1), qHash(l2)); +} + void tst_QList::reserve() const { // Note: diff --git a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp index 8c29064457..044fdbdee5 100644 --- a/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp +++ b/tests/auto/corelib/tools/qringbuffer/tst_qringbuffer.cpp @@ -52,6 +52,7 @@ private slots: void ungetChar(); void indexOf(); void appendAndRead(); + void peek(); void readLine(); }; @@ -60,7 +61,7 @@ void tst_QRingBuffer::sizeWhenReserved() QRingBuffer ringBuffer; ringBuffer.reserve(5); - QCOMPARE(ringBuffer.size(), 5); + QCOMPARE(ringBuffer.size(), Q_INT64_C(5)); } void tst_QRingBuffer::sizeWhenReservedAndChopped() @@ -69,14 +70,14 @@ void tst_QRingBuffer::sizeWhenReservedAndChopped() ringBuffer.reserve(31337); ringBuffer.chop(31337); - QCOMPARE(ringBuffer.size(), 0); + QCOMPARE(ringBuffer.size(), Q_INT64_C(0)); } void tst_QRingBuffer::sizeWhenEmpty() { QRingBuffer ringBuffer; - QCOMPARE(ringBuffer.size(), 0); + QCOMPARE(ringBuffer.size(), Q_INT64_C(0)); } void tst_QRingBuffer::readPointerAtPositionReadTooMuch() @@ -101,22 +102,22 @@ void tst_QRingBuffer::readPointerAtPositionWithHead() qint64 length; const char* buf2 = ringBuffer.readPointerAtPosition(0, length); - QCOMPARE(length, qint64(2)); + QCOMPARE(length, Q_INT64_C(2)); QVERIFY(*buf2 == '2'); QVERIFY(*(buf2+1) == '3'); // advance 2 more, ringBuffer should be empty then ringBuffer.free(2); buf2 = ringBuffer.readPointerAtPosition(0, length); - QCOMPARE(length, qint64(0)); + QCOMPARE(length, Q_INT64_C(0)); QVERIFY(buf2 == 0); // check buffer with 2 blocks memcpy(ringBuffer.reserve(4), "0123", 4); ringBuffer.append(QByteArray("45678", 5)); ringBuffer.free(3); - buf2 = ringBuffer.readPointerAtPosition(1, length); - QCOMPARE(length, qint64(5)); + buf2 = ringBuffer.readPointerAtPosition(Q_INT64_C(1), length); + QCOMPARE(length, Q_INT64_C(5)); } void tst_QRingBuffer::readPointerAtPositionEmptyRead() @@ -149,14 +150,14 @@ void tst_QRingBuffer::readPointerAtPositionWriteRead() // write in chunks of 50 bytes // this ensures there will be multiple QByteArrays inside the QRingBuffer // since QRingBuffer is then only using individual arrays of around 4000 bytes - qint64 thisWrite = qMin(remaining, qint64(50)); + qint64 thisWrite = qMin(remaining, Q_INT64_C(50)); char *pos = ringBuffer.reserve(thisWrite); inData.read(pos, thisWrite); remaining -= thisWrite; } // was data put into it? QVERIFY(ringBuffer.size() > 0); - QCOMPARE(qint64(ringBuffer.size()), inData.size()); + QCOMPARE(ringBuffer.size(), inData.size()); //read from the QRingBuffer in loop, put back into another QBuffer QBuffer outData; @@ -187,12 +188,12 @@ void tst_QRingBuffer::free() ringBuffer.append(QByteArray("01234", 5)); ringBuffer.free(1); - QCOMPARE(ringBuffer.size(), 4095 + 2048 + 5); + QCOMPARE(ringBuffer.size(), Q_INT64_C(4095 + 2048 + 5)); ringBuffer.free(4096); - QCOMPARE(ringBuffer.size(), 2047 + 5); + QCOMPARE(ringBuffer.size(), Q_INT64_C(2047 + 5)); ringBuffer.free(48); ringBuffer.free(2000); - QCOMPARE(ringBuffer.size(), 4); + QCOMPARE(ringBuffer.size(), Q_INT64_C(4)); QVERIFY(memcmp(ringBuffer.readPointer(), "1234", 4) == 0); } @@ -211,8 +212,8 @@ void tst_QRingBuffer::reserveAndRead() for (int i = 1; i < 256; ++i) { QByteArray ba; ba.resize(i); - int thisRead = ringBuffer.read(ba.data(), i); - QCOMPARE(thisRead, i); + qint64 thisRead = ringBuffer.read(ba.data(), i); + QCOMPARE(thisRead, qint64(i)); QVERIFY(ba.count(char(i)) == i); } QVERIFY(ringBuffer.size() == 0); @@ -227,12 +228,12 @@ void tst_QRingBuffer::chop() ringBuffer.reserve(4096); ringBuffer.chop(1); - QCOMPARE(ringBuffer.size(), 5 + 2048 + 4095); + QCOMPARE(ringBuffer.size(), Q_INT64_C(5 + 2048 + 4095)); ringBuffer.chop(4096); - QCOMPARE(ringBuffer.size(), 5 + 2047); + QCOMPARE(ringBuffer.size(), Q_INT64_C(5 + 2047)); ringBuffer.chop(48); ringBuffer.chop(2000); - QCOMPARE(ringBuffer.size(), 4); + QCOMPARE(ringBuffer.size(), Q_INT64_C(4)); QVERIFY(memcmp(ringBuffer.readPointer(), "0123", 4) == 0); } @@ -248,7 +249,7 @@ void tst_QRingBuffer::ungetChar() ringBuffer.getChar(); ringBuffer.ungetChar(char(c)); // unget first char } - QCOMPARE(ringBuffer.size(), 1); + QCOMPARE(ringBuffer.size(), Q_INT64_C(1)); } void tst_QRingBuffer::indexOf() @@ -258,8 +259,8 @@ void tst_QRingBuffer::indexOf() ringBuffer.putChar(char(i)); for (int i = 1; i < 256; ++i) { - int index = ringBuffer.indexOf(char(i)); - QCOMPARE(i - 1, index); + qint64 index = ringBuffer.indexOf(char(i)); + QCOMPARE(qint64(i - 1), index); QCOMPARE(index, ringBuffer.indexOf(char(i), i)); QVERIFY(ringBuffer.indexOf(char(i), i - 1) == -1); // test for absent char } @@ -280,6 +281,31 @@ void tst_QRingBuffer::appendAndRead() QVERIFY(ringBuffer.read() == ba3); } +void tst_QRingBuffer::peek() +{ + QRingBuffer ringBuffer; + QByteArray testBuffer; + // fill buffer with an arithmetic progression + for (int i = 1; i < 256; ++i) { + char *ringPos = ringBuffer.reserve(i); + QVERIFY(ringPos); + memset(ringPos, i, i); + testBuffer.append(ringPos, i); + } + + // check stored data + QByteArray resultBuffer; + int peekPosition = testBuffer.size(); + for (int i = 1; i < 256; ++i) { + QByteArray ba(i, 0); + peekPosition -= i; + qint64 thisPeek = ringBuffer.peek(ba.data(), i, peekPosition); + QCOMPARE(thisPeek, qint64(i)); + resultBuffer.prepend(ba); + } + QCOMPARE(testBuffer, resultBuffer); +} + void tst_QRingBuffer::readLine() { QRingBuffer ringBuffer; @@ -298,7 +324,7 @@ void tst_QRingBuffer::readLine() // check first empty string reading stringBuf[0] = char(0xFF); - QCOMPARE(ringBuffer.readLine(stringBuf, int(sizeof(stringBuf)) - 2), ba2.size()); + QCOMPARE(ringBuffer.readLine(stringBuf, int(sizeof(stringBuf)) - 2), qint64(ba2.size())); QVERIFY(stringBuf[0] == ba2[0]); QVERIFY(ringBuffer.readLine(stringBuf, int(sizeof(stringBuf)) - 2) == (ba3.size() + ba4.size() diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index d2f7a6ee50..d4b3ba7f15 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -60,11 +60,241 @@ #include <qhash.h> #include <string> +#include <algorithm> #define CREATE_REF(string) \ const QString padded = QString::fromLatin1(" %1 ").arg(string); \ QStringRef ref = padded.midRef(1, padded.size() - 2); +namespace { + +// this wraps an argument to a QString function, as well as how to apply +// the argument to a given QString member function. +template <typename T> +class Arg; + +template <typename T> +class Reversed {}; // marker for Arg<QChar> to apply the operation in reverse order (for prepend()) + +class ArgBase +{ +protected: + QString pinned; + explicit ArgBase(const char *str) + : pinned(QString::fromLatin1(str)) {} +}; + +template <> +class Arg<QChar> : protected ArgBase +{ +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { Q_FOREACH (QChar ch, this->pinned) (s.*mf)(ch); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { Q_FOREACH (QChar ch, this->pinned) (s.*mf)(a1, ch); } +}; + +template <> +class Arg<Reversed<QChar> > : private Arg<QChar> +{ +public: + explicit Arg(const char *str) : Arg<QChar>(str) + { + std::reverse(this->pinned.begin(), this->pinned.end()); + } + + using Arg<QChar>::apply0; + using Arg<QChar>::apply1; +}; + +template <> +class Arg<QString> : ArgBase +{ +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { (s.*mf)(this->pinned); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { (s.*mf)(a1, this->pinned); } +}; + +template <> +class Arg<QStringRef> : ArgBase +{ + QStringRef ref() const + { return this->pinned.isNull() ? QStringRef() : this->pinned.midRef(0) ; } +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { (s.*mf)(ref()); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { (s.*mf)(a1, ref()); } +}; + +template <> +class Arg<QPair<const QChar *, int> > : ArgBase +{ +public: + explicit Arg(const char *str) : ArgBase(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { (s.*mf)(this->pinned.constData(), this->pinned.length()); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { (s.*mf)(a1, this->pinned.constData(), this->pinned.length()); } +}; + +template <> +class Arg<QLatin1String> +{ + QLatin1String l1; +public: + explicit Arg(const char *str) : l1(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { (s.*mf)(l1); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { (s.*mf)(a1, l1); } +}; + +template <> +class Arg<char> +{ +protected: + const char *str; +public: + explicit Arg(const char *str) : str(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { + if (str) { + for (const char *it = str; *it; ++it) + (s.*mf)(*it); + } + } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { + if (str) { + for (const char *it = str; *it; ++it) + (s.*mf)(a1, *it); + } + } +}; + +template <> +class Arg<Reversed<char> > : private Arg<char> +{ + static const char *dupAndReverse(const char *s) + { + char *s2 = qstrdup(s); + std::reverse(s2, s2 + qstrlen(s2)); + return s2; + } +public: + explicit Arg(const char *str) : Arg<char>(dupAndReverse(str)) {} + ~Arg() { delete[] str; } + + using Arg<char>::apply0; + using Arg<char>::apply1; +}; + +template <> +class Arg<const char*> +{ + const char *str; +public: + explicit Arg(const char *str) : str(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { (s.*mf)(str); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { (s.*mf)(a1, str); } +}; + +template <> +class Arg<QByteArray> +{ + QByteArray ba; +public: + explicit Arg(const char *str) : ba(str) {} + + template <typename MemFun> + void apply0(QString &s, MemFun mf) const + { (s.*mf)(ba); } + + template <typename MemFun, typename A1> + void apply1(QString &s, MemFun mf, A1 a1) const + { (s.*mf)(a1, ba); } +}; + +// const char* is not allowed as columns in data-driven tests (causes static_assert failure), +// so wrap it in a container (default ctor is a QMetaType/QVariant requirement): +class CharStarContainer +{ + const char *str; +public: + explicit Q_DECL_CONSTEXPR CharStarContainer(const char *s = Q_NULLPTR) : str(s) {} + Q_DECL_CONSTEXPR operator const char *() const { return str; } +}; + +} // unnamed namespace + +Q_DECLARE_METATYPE(CharStarContainer) + +// implementation helpers for append_impl/prepend_impl etc +template <typename ArgType, typename MemFun> +static void do_apply0(MemFun mf) +{ + QFETCH(QString, s); + QFETCH(CharStarContainer, arg); + QFETCH(QString, expected); + + Arg<ArgType>(arg).apply0(s, mf); + + QCOMPARE(s, expected); + QCOMPARE(s.isEmpty(), expected.isEmpty()); + QCOMPARE(s.isNull(), expected.isNull()); +} + +template <typename ArgType, typename A1, typename MemFun> +static void do_apply1(MemFun mf) +{ + QFETCH(QString, s); + QFETCH(CharStarContainer, arg); + QFETCH(A1, a1); + QFETCH(QString, expected); + + Arg<ArgType>(arg).apply1(s, mf, a1); + + QCOMPARE(s, expected); + QCOMPARE(s.isEmpty(), expected.isEmpty()); + QCOMPARE(s.isNull(), expected.isNull()); +} + class tst_QString : public QObject { Q_OBJECT @@ -73,6 +303,27 @@ class tst_QString : public QObject void split_regexp(const QString &string, const QString &pattern, QStringList result); template<typename List> void split(const QString &string, const QString &separator, QStringList result); + + template <typename ArgType, typename MemFun> + void append_impl() const { do_apply0<ArgType>(MemFun(&QString::append)); } + template <typename ArgType> + void append_impl() const { append_impl<ArgType, QString &(QString::*)(const ArgType&)>(); } + void append_data(bool emptyIsNoop = false); + template <typename ArgType, typename MemFun> + void operator_pluseq_impl() const { do_apply0<ArgType>(MemFun(&QString::operator+=)); } + template <typename ArgType> + void operator_pluseq_impl() const { operator_pluseq_impl<ArgType, QString &(QString::*)(const ArgType&)>(); } + void operator_pluseq_data(bool emptyIsNoop = false); + template <typename ArgType, typename MemFun> + void prepend_impl() const { do_apply0<ArgType>(MemFun(&QString::prepend)); } + template <typename ArgType> + void prepend_impl() const { prepend_impl<ArgType, QString &(QString::*)(const ArgType&)>(); } + void prepend_data(bool emptyIsNoop = false); + template <typename ArgType, typename MemFun> + void insert_impl() const { do_apply1<ArgType, int>(MemFun(&QString::insert)); } + template <typename ArgType> + void insert_impl() const { insert_impl<ArgType, QString &(QString::*)(int, const ArgType&)>(); } + void insert_data(bool emptyIsNoop = false); public: tst_QString(); public slots: @@ -121,19 +372,86 @@ private slots: void remove_regexp_data(); void remove_regexp(); void swap(); - void prepend(); - void prepend_bytearray_data(); - void prepend_bytearray(); - void append(); - void append_bytearray_data(); - void append_bytearray(); - void operator_pluseq_bytearray_data(); - void operator_pluseq_bytearray(); + + void prepend_qstring() { prepend_impl<QString>(); } + void prepend_qstring_data() { prepend_data(true); } + void prepend_qstringref() { prepend_impl<QStringRef>(); } + void prepend_qstringref_data() { prepend_data(true); } + void prepend_qlatin1string() { prepend_impl<QLatin1String, QString &(QString::*)(QLatin1String)>(); } + void prepend_qlatin1string_data() { prepend_data(true); } + void prepend_qcharstar_int() { prepend_impl<QPair<const QChar *, int>, QString &(QString::*)(const QChar *, int)>(); } + void prepend_qcharstar_int_data() { prepend_data(true); } + void prepend_qchar() { prepend_impl<Reversed<QChar>, QString &(QString::*)(QChar)>(); } + void prepend_qchar_data() { prepend_data(true); } + void prepend_qbytearray() { prepend_impl<QByteArray>(); } + void prepend_qbytearray_data() { prepend_data(true); } + void prepend_char() { prepend_impl<Reversed<char>, QString &(QString::*)(QChar)>(); } + void prepend_char_data() { prepend_data(true); } + void prepend_charstar() { prepend_impl<const char *, QString &(QString::*)(const char *)>(); } + void prepend_charstar_data() { prepend_data(true); } + void prepend_bytearray_special_cases_data(); + void prepend_bytearray_special_cases(); + + void append_qstring() { append_impl<QString>(); } + void append_qstring_data() { append_data(); } + void append_qstringref() { append_impl<QStringRef>(); } + void append_qstringref_data() { append_data(); } + void append_qlatin1string() { append_impl<QLatin1String, QString &(QString::*)(QLatin1String)>(); } + void append_qlatin1string_data() { append_data(); } + void append_qcharstar_int() { append_impl<QPair<const QChar *, int>, QString&(QString::*)(const QChar *, int)>(); } + void append_qcharstar_int_data() { append_data(true); } + void append_qchar() { append_impl<QChar, QString &(QString::*)(QChar)>(); } + void append_qchar_data() { append_data(true); } + void append_qbytearray() { append_impl<QByteArray>(); } + void append_qbytearray_data() { append_data(); } + void append_char() { append_impl<char, QString &(QString::*)(QChar)>(); } + void append_char_data() { append_data(true); } + void append_charstar() { append_impl<const char *, QString &(QString::*)(const char *)>(); } + void append_charstar_data() { append_data(); } + void append_special_cases(); + void append_bytearray_special_cases_data(); + void append_bytearray_special_cases(); + + void operator_pluseq_qstring() { operator_pluseq_impl<QString>(); } + void operator_pluseq_qstring_data() { operator_pluseq_data(); } + void operator_pluseq_qstringref() { operator_pluseq_impl<QStringRef>(); } + void operator_pluseq_qstringref_data() { operator_pluseq_data(); } + void operator_pluseq_qlatin1string() { operator_pluseq_impl<QLatin1String, QString &(QString::*)(QLatin1String)>(); } + void operator_pluseq_qlatin1string_data() { operator_pluseq_data(); } + void operator_pluseq_qchar() { operator_pluseq_impl<QChar, QString &(QString::*)(QChar)>(); } + void operator_pluseq_qchar_data() { operator_pluseq_data(true); } + void operator_pluseq_qbytearray() { operator_pluseq_impl<QByteArray>(); } + void operator_pluseq_qbytearray_data() { operator_pluseq_data(); } + void operator_pluseq_char() { operator_pluseq_impl<char, QString &(QString::*)(char)>(); } + void operator_pluseq_char_data() { operator_pluseq_data(true); } + void operator_pluseq_charstar() { operator_pluseq_impl<const char *, QString &(QString::*)(const char *)>(); } + void operator_pluseq_charstar_data() { operator_pluseq_data(); } + void operator_pluseq_bytearray_special_cases_data(); + void operator_pluseq_bytearray_special_cases(); + void operator_eqeq_bytearray_data(); void operator_eqeq_bytearray(); void operator_eqeq_nullstring(); void operator_smaller(); - void insert(); + + void insert_qstring() { insert_impl<QString>(); } + void insert_qstring_data() { insert_data(true); } + void insert_qstringref() { insert_impl<QStringRef>(); } + void insert_qstringref_data() { insert_data(true); } + void insert_qlatin1string() { insert_impl<QLatin1String, QString &(QString::*)(int, QLatin1String)>(); } + void insert_qlatin1string_data() { insert_data(true); } + void insert_qcharstar_int() { insert_impl<QPair<const QChar *, int>, QString &(QString::*)(int, const QChar*, int) >(); } + void insert_qcharstar_int_data() { insert_data(true); } + void insert_qchar() { insert_impl<Reversed<QChar>, QString &(QString::*)(int, QChar)>(); } + void insert_qchar_data() { insert_data(true); } + void insert_qbytearray() { insert_impl<QByteArray>(); } + void insert_qbytearray_data() { insert_data(true); } + void insert_char() { insert_impl<Reversed<char>, QString &(QString::*)(int, QChar)>(); } + void insert_char_data() { insert_data(true); } + void insert_charstar() { insert_impl<const char *, QString &(QString::*)(int, const char*) >(); } + void insert_charstar_data() { insert_data(true); } + void insert_special_cases(); + void simplified_data(); void simplified(); void trimmed(); @@ -183,6 +501,7 @@ private slots: void fromLocal8Bit(); void local8Bit_data(); void local8Bit(); + void nullFromLocal8Bit(); void fromLatin1Roundtrip_data(); void fromLatin1Roundtrip(); void toLatin1Roundtrip_data(); @@ -827,7 +1146,7 @@ void tst_QString::constructorQByteArray_data() ba1[5] = 'e'; ba1[6] = 'f'; - QTest::newRow( "2" ) << ba1 << QString("abc"); + QTest::newRow( "2" ) << ba1 << QStringLiteral("abc\0def"); QTest::newRow( "3" ) << QByteArray::fromRawData("abcd", 3) << QString("abc"); QTest::newRow( "4" ) << QByteArray("\xc3\xa9") << QString("\xc3\xa9"); @@ -848,12 +1167,6 @@ void tst_QString::constructorQByteArray() QCOMPARE( strBA, expected ); // test operator= too - if (src.constData()[src.length()] == '\0') { - str1.clear(); - str1 = src.constData(); - QCOMPARE( str1, expected ); - } - strBA.clear(); strBA = src; QCOMPARE( strBA, expected ); @@ -2066,7 +2379,46 @@ void tst_QString::simplified() QCOMPARE(qMove(full).simplified(), simple); } -void tst_QString::insert() +void tst_QString::insert_data(bool emptyIsNoop) +{ + QTest::addColumn<QString>("s"); + QTest::addColumn<CharStarContainer>("arg"); + QTest::addColumn<int>("a1"); + QTest::addColumn<QString>("expected"); + + const CharStarContainer nullC; + const CharStarContainer emptyC(""); + const CharStarContainer aC("a"); + const CharStarContainer bC("b"); + //const CharStarContainer abC("ab"); + const CharStarContainer baC("ba"); + + const QString null; + const QString empty(""); + const QString a("a"); + const QString b("b"); + const QString ab("ab"); + const QString ba("ba"); + + QTest::newRow("null.insert(0, null)") << null << nullC << 0 << null; + QTest::newRow("null.insert(0, empty)") << null << emptyC << 0 << (emptyIsNoop ? null : empty); + QTest::newRow("null.insert(0, a)") << null << aC << 0 << a; + QTest::newRow("empty.insert(0, null)") << empty << nullC << 0 << empty; + QTest::newRow("empty.insert(0, empty)") << empty << emptyC << 0 << empty; + QTest::newRow("empty.insert(0, a)") << empty << aC << 0 << a; + QTest::newRow("a.insert(0, null)") << a << nullC << 0 << a; + QTest::newRow("a.insert(0, empty)") << a << emptyC << 0 << a; + QTest::newRow("a.insert(0, b)") << a << bC << 0 << ba; + QTest::newRow("a.insert(0, ba)") << a << baC << 0 << (ba + a); + QTest::newRow("a.insert(1, null)") << a << nullC << 1 << a; + QTest::newRow("a.insert(1, empty)") << a << emptyC << 1 << a; + QTest::newRow("a.insert(1, b)") << a << bC << 1 << ab; + QTest::newRow("a.insert(1, ba)") << a << baC << 1 << (a + ba); + QTest::newRow("ba.insert(1, a)") << ba << aC << 1 << (ba + a); + QTest::newRow("ba.insert(2, b)") << ba << bC << 2 << (ba + b); +} + +void tst_QString::insert_special_cases() { QString a; @@ -2097,14 +2449,37 @@ void tst_QString::insert() QCOMPARE(a.insert(0, QLatin1String("a")), QString("aMontreal")); } -void tst_QString::append() +void tst_QString::append_data(bool emptyIsNoop) { - { - QString a; - a = "<>ABCABCABCABC"; - QCOMPARE(a.append(">"),QString("<>ABCABCABCABC>")); - } + QTest::addColumn<QString>("s"); + QTest::addColumn<CharStarContainer>("arg"); + QTest::addColumn<QString>("expected"); + + const CharStarContainer nullC; + const CharStarContainer emptyC(""); + const CharStarContainer aC("a"); + const CharStarContainer bC("b"); + //const CharStarContainer abC("ab"); + const QString null; + const QString empty(""); + const QString a("a"); + //const QString b("b"); + const QString ab("ab"); + + QTest::newRow("null + null") << null << nullC << null; + QTest::newRow("null + empty") << null << emptyC << (emptyIsNoop ? null : empty); + QTest::newRow("null + a") << null << aC << a; + QTest::newRow("empty + null") << empty << nullC << empty; + QTest::newRow("empty + empty") << empty << emptyC << empty; + QTest::newRow("empty + a") << empty << aC << a; + QTest::newRow("a + null") << a << nullC << a; + QTest::newRow("a + empty") << a << emptyC << a; + QTest::newRow("a + b") << a << bC << ab; +} + +void tst_QString::append_special_cases() +{ { QString a; static const QChar unicode[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' }; @@ -2124,7 +2499,7 @@ void tst_QString::append() } } -void tst_QString::append_bytearray_data() +void tst_QString::append_bytearray_special_cases_data() { QTest::addColumn<QString>("str" ); QTest::addColumn<QByteArray>("ba" ); @@ -2158,7 +2533,7 @@ void tst_QString::append_bytearray_data() QTest::newRow( "nonAsciiByteArray2") << QString() << QByteArray("\xc3\xa9") << QString::fromUtf8("\xc3\xa9"); } -void tst_QString::append_bytearray() +void tst_QString::append_bytearray_special_cases() { { QFETCH( QString, str ); @@ -2176,22 +2551,19 @@ void tst_QString::append_bytearray() QTEST( str, "res" ); } +} - QFETCH( QByteArray, ba ); - if (ba.constData()[ba.length()] == '\0') { - QFETCH( QString, str ); - - str.append(ba.constData()); - QTEST( str, "res" ); - } +void tst_QString::operator_pluseq_data(bool emptyIsNoop) +{ + append_data(emptyIsNoop); } -void tst_QString::operator_pluseq_bytearray_data() +void tst_QString::operator_pluseq_bytearray_special_cases_data() { - append_bytearray_data(); + append_bytearray_special_cases_data(); } -void tst_QString::operator_pluseq_bytearray() +void tst_QString::operator_pluseq_bytearray_special_cases() { { QFETCH( QString, str ); @@ -2209,14 +2581,6 @@ void tst_QString::operator_pluseq_bytearray() QTEST( str, "res" ); } - - QFETCH( QByteArray, ba ); - if (ba.constData()[ba.length()] == '\0') { - QFETCH( QString, str ); - - str += ba.constData(); - QTEST( str, "res" ); - } } void tst_QString::operator_eqeq_bytearray_data() @@ -2231,11 +2595,6 @@ void tst_QString::operator_eqeq_bytearray() QVERIFY(expected == src); QVERIFY(!(expected != src)); - - if (src.constData()[src.length()] == '\0') { - QVERIFY(expected == src.constData()); - QVERIFY(!(expected != src.constData())); - } } void tst_QString::swap() @@ -2248,14 +2607,37 @@ void tst_QString::swap() QCOMPARE(s2,QLatin1String("s1")); } -void tst_QString::prepend() +void tst_QString::prepend_data(bool emptyIsNoop) { - QString a; - a = "<>ABCABCABCABC>"; - QCOMPARE(a.prepend("-"),(QString)"-<>ABCABCABCABC>"); + QTest::addColumn<QString>("s"); + QTest::addColumn<CharStarContainer>("arg"); + QTest::addColumn<QString>("expected"); + + const CharStarContainer nullC; + const CharStarContainer emptyC(""); + const CharStarContainer aC("a"); + const CharStarContainer bC("b"); + const CharStarContainer baC("ba"); + + const QString null; + const QString empty(""); + const QString a("a"); + //const QString b("b"); + const QString ba("ba"); + + QTest::newRow("null.prepend(null)") << null << nullC << null; + QTest::newRow("null.prepend(empty)") << null << emptyC << (emptyIsNoop ? null : empty); + QTest::newRow("null.prepend(a)") << null << aC << a; + QTest::newRow("empty.prepend(null)") << empty << nullC << empty; + QTest::newRow("empty.prepend(empty)") << empty << emptyC << empty; + QTest::newRow("empty.prepend(a)") << empty << aC << a; + QTest::newRow("a.prepend(null)") << a << nullC << a; + QTest::newRow("a.prepend(empty)") << a << emptyC << a; + QTest::newRow("a.prepend(b)") << a << bC << ba; + QTest::newRow("a.prepend(ba)") << a << baC << (ba + a); } -void tst_QString::prepend_bytearray_data() +void tst_QString::prepend_bytearray_special_cases_data() { QTest::addColumn<QString>("str" ); QTest::addColumn<QByteArray>("ba" ); @@ -2270,7 +2652,7 @@ void tst_QString::prepend_bytearray_data() // byte array with only a 0 ba.resize( 1 ); ba[0] = 0; - QTest::newRow( "emptyString" ) << QString("foobar ") << ba << QString("foobar "); + QTest::newRow( "emptyString" ) << QString("foobar ") << ba << QStringLiteral("\0foobar "); // empty byte array ba.resize( 0 ); @@ -2281,7 +2663,7 @@ void tst_QString::prepend_bytearray_data() QTest::newRow( "nonAsciiByteArray2") << QString() << QByteArray("\xc3\xa9") << QString::fromUtf8("\xc3\xa9"); } -void tst_QString::prepend_bytearray() +void tst_QString::prepend_bytearray_special_cases() { { QFETCH( QString, str ); @@ -2300,14 +2682,6 @@ void tst_QString::prepend_bytearray() QTEST( str, "res" ); } - - QFETCH( QByteArray, ba ); - if (ba.constData()[ba.length()] == '\0') { - QFETCH( QString, str ); - - str.prepend(ba.constData()); - QTEST( str, "res" ); - } } void tst_QString::replace_uint_uint() @@ -3697,6 +4071,12 @@ void tst_QString::nullFromUtf8() a = QString::fromUtf8(""); QVERIFY(!a.isNull()); QVERIFY(a.isEmpty()); + a = QString::fromUtf8(QByteArray()); + QVERIFY(a.isNull()); + QVERIFY(a.isEmpty()); + a = QString::fromUtf8(QByteArray("")); + QVERIFY(!a.isNull()); + QVERIFY(a.isEmpty()); } void tst_QString::fromLocal8Bit_data() @@ -3779,6 +4159,23 @@ void tst_QString::local8Bit() QCOMPARE(local8Bit.toLocal8Bit(), QByteArray(result)); } +void tst_QString::nullFromLocal8Bit() +{ + QString a; + a = QString::fromLocal8Bit(0); + QVERIFY(a.isNull()); + QVERIFY(a.isEmpty()); + a = QString::fromLocal8Bit(""); + QVERIFY(!a.isNull()); + QVERIFY(a.isEmpty()); + a = QString::fromLocal8Bit(QByteArray()); + QVERIFY(a.isNull()); + QVERIFY(a.isEmpty()); + a = QString::fromLocal8Bit(QByteArray("")); + QVERIFY(!a.isNull()); + QVERIFY(a.isEmpty()); +} + void tst_QString::stringRef_local8Bit_data() { local8Bit_data(); @@ -3945,6 +4342,12 @@ void tst_QString::fromLatin1() a = QString::fromLatin1( "" ); QVERIFY( !a.isNull() ); QVERIFY( a.isEmpty() ); + a = QString::fromLatin1(QByteArray()); + QVERIFY(a.isNull()); + QVERIFY(a.isEmpty()); + a = QString::fromLatin1(QByteArray("")); + QVERIFY(!a.isNull()); + QVERIFY(a.isEmpty()); a = QString::fromLatin1(0, 0); QVERIFY(a.isNull()); diff --git a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp index 5d12cd9804..719daad3b6 100644 --- a/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/corelib/tools/qvarlengtharray/tst_qvarlengtharray.cpp @@ -47,10 +47,12 @@ private slots: void appendCausingRealloc(); void resize(); void realloc(); + void reverseIterators(); void count(); void first(); void last(); void squeeze(); + void operators(); void indexOf(); void lastIndexOf(); void contains(); @@ -562,6 +564,21 @@ void tst_QVarLengthArray::realloc() QVERIFY(reallocTestProceed); } +void tst_QVarLengthArray::reverseIterators() +{ + QVarLengthArray<int> v; + v << 1 << 2 << 3 << 4; + QVarLengthArray<int> vr = v; + std::reverse(vr.begin(), vr.end()); + const QVarLengthArray<int> &cvr = vr; + QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin())); + QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin())); + QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin())); + QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin())); + QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin())); + QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin())); +} + void tst_QVarLengthArray::count() { // tests size(), count() and length(), since they're the same thing @@ -690,6 +707,49 @@ void tst_QVarLengthArray::squeeze() QCOMPARE(list.capacity(), sizeOnHeap); } +void tst_QVarLengthArray::operators() +{ + QVarLengthArray<QString> myvla; + myvla << "A" << "B" << "C"; + QVarLengthArray<QString> myvlatwo; + myvlatwo << "D" << "E" << "F"; + QVarLengthArray<QString> combined; + combined << "A" << "B" << "C" << "D" << "E" << "F"; + + // != + QVERIFY(myvla != myvlatwo); + + // +=: not provided, emulate + //myvla += myvlatwo; + Q_FOREACH (const QString &s, myvlatwo) + myvla.push_back(s); + QCOMPARE(myvla, combined); + + // == + QVERIFY(myvla == combined); + + // <, >, <=, >= + QVERIFY(!(myvla < combined)); + QVERIFY(!(myvla > combined)); + QVERIFY( myvla <= combined); + QVERIFY( myvla >= combined); + combined.push_back("G"); + QVERIFY( myvla < combined); + QVERIFY(!(myvla > combined)); + QVERIFY( myvla <= combined); + QVERIFY(!(myvla >= combined)); + QVERIFY(combined > myvla); + QVERIFY(combined >= myvla); + + // [] + QCOMPARE(myvla[0], QLatin1String("A")); + QCOMPARE(myvla[1], QLatin1String("B")); + QCOMPARE(myvla[2], QLatin1String("C")); + QCOMPARE(myvla[3], QLatin1String("D")); + QCOMPARE(myvla[4], QLatin1String("E")); + QCOMPARE(myvla[5], QLatin1String("F")); +} + void tst_QVarLengthArray::indexOf() { QVarLengthArray<QString> myvec; diff --git a/tests/auto/corelib/tools/qvector/tst_qvector.cpp b/tests/auto/corelib/tools/qvector/tst_qvector.cpp index 69da6e450e..3f95fa18f6 100644 --- a/tests/auto/corelib/tools/qvector/tst_qvector.cpp +++ b/tests/auto/corelib/tools/qvector/tst_qvector.cpp @@ -86,6 +86,8 @@ private: } }; +inline uint qHash(const Movable &key, uint seed = 0) { return qHash(key.i, seed); } + QAtomicInt Movable::counter = 0; QT_BEGIN_NAMESPACE Q_DECLARE_TYPEINFO(Movable, Q_MOVABLE_TYPE); @@ -123,6 +125,13 @@ struct Custom { return i == other.i; } + bool operator<(const Custom &other) const + { + check(&other); + check(this); + return i < other.i; + } + Custom &operator=(const Custom &other) { check(&other); @@ -148,6 +157,8 @@ private: }; QAtomicInt Custom::counter = 0; +inline uint qHash(const Custom &key, uint seed = 0) { return qHash(key.i, seed); } + Q_DECLARE_METATYPE(Custom); // tests depends on the fact that: @@ -230,6 +241,9 @@ private slots: void prependInt() const; void prependMovable() const; void prependCustom() const; + void qhashInt() const { qhash<int>(); } + void qhashMovable() const { qhash<Movable>(); } + void qhashCustom() const { qhash<Custom>(); } void removeInt() const; void removeMovable() const; void removeCustom() const; @@ -241,6 +255,7 @@ private slots: void resizeComplex_data() const; void resizeComplex() const; void resizeCtorAndDtor() const; + void reverseIterators() const; void sizeInt() const; void sizeMovable() const; void sizeCustom() const; @@ -294,6 +309,7 @@ private: template<typename T> void fill() const; template<typename T> void fromList() const; template<typename T> void insert() const; + template<typename T> void qhash() const; template<typename T> void prepend() const; template<typename T> void remove() const; template<typename T> void size() const; @@ -1437,6 +1453,16 @@ void tst_QVector::mid() const QCOMPARE(list.mid(4), QVector<QString>() << "buck" << "hello" << "kitty"); } +template <typename T> +void tst_QVector::qhash() const +{ + QVector<T> l1, l2; + QCOMPARE(qHash(l1), qHash(l2)); + l1 << SimpleValue<T>::at(0); + l2 << SimpleValue<T>::at(0); + QCOMPARE(qHash(l1), qHash(l2)); +} + template<typename T> void tst_QVector::prepend() const { @@ -1907,6 +1933,21 @@ void tst_QVector::resizeCtorAndDtor() const QCOMPARE(Custom::counter.loadAcquire(), items); } +void tst_QVector::reverseIterators() const +{ + QVector<int> v; + v << 1 << 2 << 3 << 4; + QVector<int> vr = v; + std::reverse(vr.begin(), vr.end()); + const QVector<int> &cvr = vr; + QVERIFY(std::equal(v.begin(), v.end(), vr.rbegin())); + QVERIFY(std::equal(v.begin(), v.end(), vr.crbegin())); + QVERIFY(std::equal(v.begin(), v.end(), cvr.rbegin())); + QVERIFY(std::equal(vr.rbegin(), vr.rend(), v.begin())); + QVERIFY(std::equal(vr.crbegin(), vr.crend(), v.begin())); + QVERIFY(std::equal(cvr.rbegin(), cvr.rend(), v.begin())); +} + template<typename T> void tst_QVector::size() const { @@ -2076,6 +2117,19 @@ void tst_QVector::testOperators() const // == QVERIFY(myvec == combined); + // <, >, <=, >= + QVERIFY(!(myvec < combined)); + QVERIFY(!(myvec > combined)); + QVERIFY( myvec <= combined); + QVERIFY( myvec >= combined); + combined.push_back("G"); + QVERIFY( myvec < combined); + QVERIFY(!(myvec > combined)); + QVERIFY( myvec <= combined); + QVERIFY(!(myvec >= combined)); + QVERIFY(combined > myvec); + QVERIFY(combined >= myvec); + // [] QCOMPARE(myvec[0], QLatin1String("A")); QCOMPARE(myvec[1], QLatin1String("B")); diff --git a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp index 32c228c186..d85e842a23 100644 --- a/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp +++ b/tests/auto/dbus/qdbusconnection/tst_qdbusconnection.cpp @@ -105,6 +105,8 @@ private slots: void sendWithGui(); void sendAsync(); void sendSignal(); + void sendSignalToName(); + void sendSignalToOtherName(); void registerObject_data(); void registerObject(); @@ -189,6 +191,49 @@ void tst_QDBusConnection::sendSignal() QTest::qWait(1000); } +void tst_QDBusConnection::sendSignalToName() +{ + QDBusSpy spy; + + QDBusConnection con = QDBusConnection::sessionBus(); + + con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy, + SLOT(handlePing(QString))); + + QDBusMessage msg = + QDBusMessage::createTargetedSignal(con.baseService(), "/org/kde/selftest", + "org.kde.selftest", "ping"); + msg << QLatin1String("ping"); + + QVERIFY(con.send(msg)); + + QTest::qWait(1000); + + QCOMPARE(spy.args.count(), 1); + QCOMPARE(spy.args.at(0).toString(), QString("ping")); +} + +void tst_QDBusConnection::sendSignalToOtherName() +{ + QDBusSpy spy; + + QDBusConnection con = QDBusConnection::sessionBus(); + + con.connect(con.baseService(), "/org/kde/selftest", "org.kde.selftest", "ping", &spy, + SLOT(handlePing(QString))); + + QDBusMessage msg = + QDBusMessage::createTargetedSignal("some.other.service", "/org/kde/selftest", + "org.kde.selftest", "ping"); + msg << QLatin1String("ping"); + + QVERIFY(con.send(msg)); + + QTest::qWait(1000); + + QCOMPARE(spy.args.count(), 0); +} + void tst_QDBusConnection::send() { QDBusConnection con = QDBusConnection::sessionBus(); diff --git a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp index 76e740dc5f..11c292db91 100644 --- a/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp +++ b/tests/auto/dbus/qdbusmarshall/tst_qdbusmarshall.cpp @@ -874,7 +874,7 @@ void tst_QDBusMarshall::sendSignalErrors() "signalName"); msg << QVariant::fromValue(QDBusObjectPath()); - QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal to service \"\" path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); QVERIFY(!con.send(msg)); msg.setArguments(QVariantList()); @@ -884,19 +884,19 @@ void tst_QDBusMarshall::sendSignalErrors() path.setPath("abc"); msg << QVariant::fromValue(path); - QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal to service \"\" path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid object path passed in arguments"); QVERIFY(!con.send(msg)); QDBusSignature sig; msg.setArguments(QVariantList() << QVariant::fromValue(sig)); - QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal to service \"\" path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); QVERIFY(!con.send(msg)); QTest::ignoreMessage(QtWarningMsg, "QDBusSignature: invalid signature \"a\""); sig.setSignature("a"); msg.setArguments(QVariantList()); msg << QVariant::fromValue(sig); - QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); + QTest::ignoreMessage(QtWarningMsg, "QDBusConnection: error: could not send signal to service \"\" path \"/foo\" interface \"local.interfaceName\" member \"signalName\": Marshalling failed: Invalid signature passed in arguments"); QVERIFY(!con.send(msg)); } diff --git a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp index 4fafbf9827..cf0d82f3f7 100644 --- a/tests/auto/gui/painting/qcolor/tst_qcolor.cpp +++ b/tests/auto/gui/painting/qcolor/tst_qcolor.cpp @@ -39,6 +39,7 @@ #include <qcolor.h> #include <qdebug.h> #include <private/qdrawingprimitive_sse2_p.h> +#include <qrgba64.h> class tst_QColor : public QObject { @@ -105,6 +106,9 @@ private slots: void premultiply(); void unpremultiply_sse4(); + void qrgba64(); + void qrgba64Premultiply(); + void qrgba64Equivalence(); #ifdef Q_DEAD_CODE_FROM_QT4_X11 void setallowX11ColorNames(); @@ -1464,5 +1468,84 @@ void tst_QColor::unpremultiply_sse4() QSKIP("SSE4 not supported on this CPU."); } +void tst_QColor::qrgba64() +{ + QRgba64 rgb64 = QRgba64::fromRgba(0x22, 0x33, 0x44, 0xff); + QCOMPARE(rgb64.red(), quint16(0x2222)); + QCOMPARE(rgb64.green(), quint16(0x3333)); + QCOMPARE(rgb64.blue(), quint16(0x4444)); + QCOMPARE(rgb64.alpha(), quint16(0xffff)); + + QColor c(rgb64); + QCOMPARE(c.red(), 0x22); + QCOMPARE(c.green(), 0x33); + QCOMPARE(c.blue(), 0x44); + + QCOMPARE(c.rgba64(), rgb64); + + QColor c2 = QColor::fromRgb(0x22, 0x33, 0x44, 0xff); + QCOMPARE(c, c2); + QCOMPARE(c2.rgba64(), rgb64); + + rgb64.setAlpha(0x8000); + rgb64.setGreen(0x8844); + rgb64 = rgb64.premultiplied(); + QCOMPARE(rgb64.red(), quint16(0x1111)); + QCOMPARE(rgb64.blue(), quint16(0x2222)); + QCOMPARE(rgb64.green(), quint16(0x4422)); +} + +void tst_QColor::qrgba64Premultiply() +{ + // Tests that qPremultiply(qUnpremultiply(rgba64)) returns rgba64. + for (uint a = 0; a < 0x10000; a+=7) { + const uint step = std::max(a/1024, 1u); + for (uint c = 0; c <= a; c+=step) { + QRgba64 p = qRgba64(c, a-c, a-c/2, a); + QRgba64 pp = qPremultiply(qUnpremultiply(p)); + QCOMPARE(pp, p); + } + } +} + +void tst_QColor::qrgba64Equivalence() +{ + // Any ARGB32 converted back and forth. + for (uint a = 0; a < 256; a++) { + for (uint c = 0; c < 256; c++) { + QRgb p1 = qRgba(c, 255-c, 255-c, a); + QRgba64 p64 = QRgba64::fromArgb32(p1); + QCOMPARE(p64.toArgb32(), p1); + } + } + // Any unpremultiplied ARGB32 value premultipled in RGB64 (except alpha 0). + for (uint a = 1; a < 256; a++) { + for (uint c = 0; c < 256; c++) { + QRgb p1 = qRgba(c, 255-c, 255-c, a); + QRgb pp1 = qPremultiply(p1); + QRgba64 pp64 = qPremultiply(QRgba64::fromArgb32(p1)); + QRgb pp2 = pp64.toArgb32(); + // 64bit premultiplied is more accurate than 32bit, so allow slight difference. + QCOMPARE(qAlpha(pp2), qAlpha(pp1)); + QVERIFY(qAbs(qRed(pp2)-qRed(pp1)) <= 1); + QVERIFY(qAbs(qGreen(pp2)-qGreen(pp1)) <= 1); + QVERIFY(qAbs(qBlue(pp2)-qBlue(pp1)) <= 1); + // But verify the added accuracy means we can return to accurate unpremultiplied ARGB32. + QRgba64 pu64 = qUnpremultiply(pp64); + QRgb p2 = pu64.toArgb32(); + QCOMPARE(p2, p1); + } + } + // Any premultiplied ARGB32 value unpremultipled in RGB64. + for (uint a = 0; a < 256; a++) { + for (uint c = 0; c <= a; c++) { + QRgb pp = qRgba(c, a-c, a-c, a); + QRgb pu = qUnpremultiply(pp); + QRgba64 pu64 = qUnpremultiply(QRgba64::fromArgb32(pp)); + QCOMPARE(pu64.toArgb32(), pu); + } + } +} + QTEST_MAIN(tst_QColor) #include "tst_qcolor.moc" diff --git a/tests/auto/gui/painting/qpainter/qpainter.pro b/tests/auto/gui/painting/qpainter/qpainter.pro index 7e9d438e1b..e90b516ef2 100644 --- a/tests/auto/gui/painting/qpainter/qpainter.pro +++ b/tests/auto/gui/painting/qpainter/qpainter.pro @@ -2,7 +2,7 @@ CONFIG += testcase CONFIG += parallel_test TARGET = tst_qpainter -QT += testlib +QT += testlib gui-private core-private qtHaveModule(widgets): QT += widgets widgets-private SOURCES += tst_qpainter.cpp diff --git a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp index 6582755aec..e13a6b026d 100644 --- a/tests/auto/gui/painting/qpainter/tst_qpainter.cpp +++ b/tests/auto/gui/painting/qpainter/tst_qpainter.cpp @@ -53,6 +53,7 @@ #endif #include <qpixmap.h> +#include <private/qdrawhelper_p.h> #include <qpainter.h> #ifndef QT_NO_WIDGETS @@ -125,8 +126,12 @@ private slots: void fillRect3(); void fillRect4_data() { fillRect2_data(); } void fillRect4(); + void fillRectNonPremul_data(); void fillRectNonPremul(); + void fillRectRGB30_data(); + void fillRectRGB30(); + void drawEllipse_data(); void drawEllipse(); void drawClippedEllipse_data(); @@ -198,6 +203,11 @@ private slots: void gradientPixelFormat_data(); void gradientPixelFormat(); + void linearGradientRgb30_data(); + void linearGradientRgb30(); + void radialGradientRgb30_data(); + void radialGradientRgb30(); + void fpe_pixmapTransform(); void fpe_zeroLengthLines(); void fpe_divByZero(); @@ -1245,22 +1255,87 @@ void tst_QPainter::fillRect4() QCOMPARE(image, expected); } +void tst_QPainter::fillRectNonPremul_data() +{ + QTest::addColumn<QImage::Format>("format"); + QTest::addColumn<uint>("color"); + + QTest::newRow("argb32 7f1f3f7f") << QImage::Format_ARGB32 << qRgba(31, 63, 127, 127); + QTest::newRow("rgba8888 7f1f3f7f") << QImage::Format_RGBA8888 << qRgba(31, 63, 127, 127); + + QTest::newRow("argb32 3f1f3f7f") << QImage::Format_ARGB32 << qRgba(31, 63, 127, 63); + QTest::newRow("rgba8888 3f1f3f7f") << QImage::Format_RGBA8888 << qRgba(31, 63, 127, 63); + + QTest::newRow("argb32 070375f4") << QImage::Format_ARGB32 << qRgba(3, 117, 244, 7); + QTest::newRow("rgba8888 070375f4") << QImage::Format_RGBA8888 << qRgba(3, 117, 244, 7); + + QTest::newRow("argb32 0301fe0c") << QImage::Format_ARGB32 << qRgba(1, 254, 12, 3); + QTest::newRow("rgba8888 0301fe0c") << QImage::Format_RGBA8888 << qRgba(1, 254, 12, 3); + + QTest::newRow("argb32 01804010") << QImage::Format_ARGB32 << qRgba(128, 64, 32, 1); + QTest::newRow("rgba8888 01804010") << QImage::Format_RGBA8888 << qRgba(128, 64, 32, 1); +} + void tst_QPainter::fillRectNonPremul() { - QImage img1(1, 1, QImage::Format_ARGB32); - QImage img2(1, 1, QImage::Format_RGBA8888); + QFETCH(QImage::Format, format); + QFETCH(uint, color); + + QImage image(1, 1, format); + QRectF rect(0, 0, 1, 1); - QPainter p1(&img1); - QPainter p2(&img2); + // Fill with CompositionMode_SourceOver tests blend_color + image.fill(Qt::transparent); + QPainter painter(&image); + painter.fillRect(rect, QColor::fromRgba(color)); + painter.end(); + + // Fill with CompositionMode_Source tests rectfill. + painter.begin(&image); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(rect, QColor::fromRgba(color)); + painter.end(); + + QRgb p = image.pixel(0, 0); + QCOMPARE(qAlpha(p), qAlpha(color)); + QVERIFY(qAbs(qRed(p)-qRed(color)) <= 1); + QVERIFY(qAbs(qGreen(p)-qGreen(color)) <= 1); + QVERIFY(qAbs(qBlue(p)-qBlue(color)) <= 1); +} + +void tst_QPainter::fillRectRGB30_data() +{ + QTest::addColumn<uint>("color"); + QTest::newRow("17|43|259") << (0xc0000000 | (17 << 20) | (43 << 10) | 259); + QTest::newRow("2|33|444") << (0xc0000000 | (2 << 20) | (33 << 10) | 444); + QTest::newRow("1000|1000|1000") << (0xc0000000 | (1000 << 20) | (1000 << 10) | 1000); +} + +void tst_QPainter::fillRectRGB30() +{ + QFETCH(uint, color); QRectF rect(0, 0, 1, 1); - p1.fillRect(rect, qRgba(31, 63, 127, 127)); - p2.fillRect(rect, qRgba(31, 63, 127, 127)); - p1.end(); - p2.end(); + // Fill with CompositionMode_SourceOver tests blend_color + QImage image1(1, 1, QImage::Format_A2BGR30_Premultiplied); + image1.fill(Qt::transparent); + QPainter painter(&image1); + painter.fillRect(rect, QColor::fromRgba64(qConvertA2rgb30ToRgb64<PixelOrderBGR>(color))); + painter.end(); + + uint pixel1 = ((const uint*)(image1.bits()))[0]; + QCOMPARE(pixel1, color); - QCOMPARE(img1.pixel(0, 0), img2.pixel(0,0)); + // Fill with CompositionMode_Source tests rectfill. + QImage image2(1, 1, QImage::Format_RGB30); + painter.begin(&image2); + painter.setCompositionMode(QPainter::CompositionMode_Source); + painter.fillRect(rect, QColor::fromRgba64(qConvertA2rgb30ToRgb64<PixelOrderRGB>(color))); + painter.end(); + + uint pixel2 = ((const uint*)(image2.bits()))[0]; + QCOMPARE(pixel2, color); } void tst_QPainter::drawPath_data() @@ -2381,36 +2456,50 @@ void tst_QPainter::setOpacity_data() QTest::newRow("RGBx8888 on RGBx8888") << QImage::Format_RGBX8888 << QImage::Format_RGBX8888; - QTest::newRow("RGBA8888P on ARGB32P") << QImage::Format_RGBA8888_Premultiplied + QTest::newRow("RGBA8888P on ARGB32P") << QImage::Format_ARGB32_Premultiplied + << QImage::Format_RGBA8888_Premultiplied; + + QTest::newRow("RGBx8888 on ARGB32P") << QImage::Format_ARGB32_Premultiplied + << QImage::Format_RGBX8888; + + QTest::newRow("ARGB32P on RGBA8888P") << QImage::Format_RGBA8888_Premultiplied << QImage::Format_ARGB32_Premultiplied; - QTest::newRow("RGBx8888 on ARGB32P") << QImage::Format_RGBX8888 - << QImage::Format_ARGB32_Premultiplied; + QTest::newRow("RGB32 on RGBx8888") << QImage::Format_RGBX8888 + << QImage::Format_RGB32; - QTest::newRow("ARGB32P on RGBA8888P") << QImage::Format_ARGB32_Premultiplied - << QImage::Format_RGBA8888_Premultiplied; + QTest::newRow("RGB30 on RGB32") << QImage::Format_RGB32 + << QImage::Format_BGR30; - QTest::newRow("RGB32 on RGBx8888") << QImage::Format_RGB32 - << QImage::Format_RGBX8888; + QTest::newRow("BGR30 on ARGB32P") << QImage::Format_ARGB32_Premultiplied + << QImage::Format_BGR30; + + QTest::newRow("A2RGB30P on ARGB32P") << QImage::Format_ARGB32_Premultiplied + << QImage::Format_A2BGR30_Premultiplied; QTest::newRow("A2RGB30P on A2RGB30P") << QImage::Format_A2RGB30_Premultiplied << QImage::Format_A2RGB30_Premultiplied; - QTest::newRow("ARGB32P on A2RGB30P") << QImage::Format_ARGB32_Premultiplied - << QImage::Format_A2RGB30_Premultiplied; + QTest::newRow("ARGB32P on A2RGB30P") << QImage::Format_A2RGB30_Premultiplied + << QImage::Format_ARGB32_Premultiplied; + + QTest::newRow("RGB32 on A2BGR30P") << QImage::Format_A2BGR30_Premultiplied + << QImage::Format_RGB32; + QTest::newRow("RGB30 on A2BGR30P") << QImage::Format_A2BGR30_Premultiplied + << QImage::Format_RGB30; - QTest::newRow("RGB32 on A2BGR30P") << QImage::Format_ARGB32_Premultiplied - << QImage::Format_A2BGR30_Premultiplied; + QTest::newRow("A2RGB30P on A2BGR30P") << QImage::Format_A2BGR30_Premultiplied + << QImage::Format_A2RGB30_Premultiplied; - QTest::newRow("A2RGB30P on A2BGR30P") << QImage::Format_A2RGB30_Premultiplied - << QImage::Format_A2BGR30_Premultiplied; + QTest::newRow("ARGB32P on BGR30") << QImage::Format_BGR30 + << QImage::Format_ARGB32_Premultiplied; - QTest::newRow("ARGB32P on BGR30") << QImage::Format_ARGB32_Premultiplied - << QImage::Format_BGR30; + QTest::newRow("ARGB32P on RGB30") << QImage::Format_RGB30 + << QImage::Format_ARGB32_Premultiplied; - QTest::newRow("ARGB32P on RGB30") << QImage::Format_A2RGB30_Premultiplied - << QImage::Format_RGB30; + QTest::newRow("A2RGB30P on RGB30") << QImage::Format_RGB30 + << QImage::Format_A2RGB30_Premultiplied; } @@ -2492,7 +2581,7 @@ void tst_QPainter::drawhelper_blend_untransformed() QImage expected(size - 2, size, destFormat); p.begin(&expected); p.fillRect(0, 0, expected.width(), expected.height(), - QColor(dest.pixel(1, 0))); + dest.pixelColor(1, 0)); p.end(); const QImage subDest(dest.bits() + dest.depth() / 8, @@ -2500,9 +2589,7 @@ void tst_QPainter::drawhelper_blend_untransformed() dest.bytesPerLine(), dest.format()); if (dest.format() == QImage::Format_ARGB8565_Premultiplied || - dest.format() == QImage::Format_ARGB8555_Premultiplied || - dest.format() == QImage::Format_A2BGR30_Premultiplied || - dest.format() == QImage::Format_A2RGB30_Premultiplied ) { + dest.format() == QImage::Format_ARGB8555_Premultiplied) { // Test skipped due to rounding errors... continue; } @@ -2551,7 +2638,7 @@ void tst_QPainter::drawhelper_blend_tiled_untransformed() QImage expected(size - 2, size, destFormat); p.begin(&expected); p.fillRect(0, 0, expected.width(), expected.height(), - QColor(dest.pixel(1, 0))); + dest.pixelColor(1, 0)); p.end(); const QImage subDest(dest.bits() + dest.depth() / 8, @@ -2619,28 +2706,6 @@ void tst_QPainter::porterDuff_warning() QVERIFY(qInstallMessageHandler(old) == porterDuff_warningChecker); } -class quint24 -{ -public: - inline quint24(quint32 v) - { - data[0] = qBlue(v); - data[1] = qGreen(v); - data[2] = qRed(v); - } - - inline operator quint32 () - { - return qRgb(data[2], data[1], data[0]); - } - - inline bool operator==(const quint24 &v) const { - return (data[0] == v.data[0] && data[1] == v.data[1] && data[2] == v.data[2]); - } - - uchar data[3]; -}; - void tst_QPainter::drawhelper_blend_color() { QImage dest(32, 32, QImage::Format_ARGB8555_Premultiplied); @@ -3889,6 +3954,65 @@ void tst_QPainter::gradientInterpolation() } } +void tst_QPainter::linearGradientRgb30_data() +{ + QTest::addColumn<QColor>("stop0"); + QTest::addColumn<QColor>("stop1"); + + QTest::newRow("white->black") << QColor(Qt::white) << QColor(Qt::black); + QTest::newRow("blue->black") << QColor(Qt::blue) << QColor(Qt::black); + QTest::newRow("white->red") << QColor(Qt::white) << QColor(Qt::red); +} + +void tst_QPainter::linearGradientRgb30() +{ + QFETCH(QColor, stop0); + QFETCH(QColor, stop1); + + QLinearGradient gradient(0, 0, 1000, 1); + gradient.setColorAt(0.0, stop0); + gradient.setColorAt(1.0, stop1); + + QImage image(1000, 1, QImage::Format_RGB30); + QPainter painter(&image); + painter.fillRect(image.rect(), gradient); + painter.end(); + + for (int i = 1; i < 1000; ++i) { + QColor p1 = image.pixelColor(i - 1, 0); + QColor p2 = image.pixelColor(i, 0); + QVERIFY(p1 != p2); + QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb())); + } +} + +void tst_QPainter::radialGradientRgb30_data() +{ + linearGradientRgb30_data(); +} + +void tst_QPainter::radialGradientRgb30() +{ + QFETCH(QColor, stop0); + QFETCH(QColor, stop1); + + QRadialGradient gradient(0, 0, 1000); + gradient.setColorAt(0.0, stop0); + gradient.setColorAt(1.0, stop1); + + QImage image(1000, 1, QImage::Format_A2BGR30_Premultiplied); + QPainter painter(&image); + painter.fillRect(image.rect(), gradient); + painter.end(); + + for (int i = 1; i < 1000; ++i) { + QColor p1 = image.pixelColor(i - 1, 0); + QColor p2 = image.pixelColor(i, 0); + QVERIFY(p1 != p2); + QVERIFY(qGray(p1.rgb()) >= qGray(p2.rgb())); + } +} + void tst_QPainter::drawPolygon() { QImage img(128, 128, QImage::Format_ARGB32_Premultiplied); @@ -4064,10 +4188,10 @@ void tst_QPainter::extendedBlendModes() QVERIFY(testCompositionMode(255, 255, 255, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode( 0, 0, 0, QPainter::CompositionMode_Plus, 0.3)); - QVERIFY(testCompositionMode(127, 128, 165, QPainter::CompositionMode_Plus, 0.3)); - QVERIFY(testCompositionMode(127, 0, 37, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(126, 128, 165, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(127, 0, 38, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode( 0, 127, 127, QPainter::CompositionMode_Plus, 0.3)); - QVERIFY(testCompositionMode(255, 0, 75, QPainter::CompositionMode_Plus, 0.3)); + QVERIFY(testCompositionMode(255, 0, 76, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode( 0, 255, 255, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode(128, 128, 166, QPainter::CompositionMode_Plus, 0.3)); QVERIFY(testCompositionMode(186, 200, 255, QPainter::CompositionMode_Plus, 0.3)); @@ -4752,6 +4876,18 @@ void tst_QPainter::blendARGBonRGB_data() << QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 125; QTest::newRow("ARGB_PM source-in RGB666") << QImage::Format_RGB666 << QImage::Format_ARGB32_Premultiplied << QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 125; + QTest::newRow("ARGB over RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32 + << QPainter::CompositionMode_SourceOver << qRgba(255, 0, 0, 127) << 127; + QTest::newRow("ARGB_PM over RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied + << QPainter::CompositionMode_SourceOver << qRgba(127, 0, 0, 127) << 127; + QTest::newRow("ARGB source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32 + << QPainter::CompositionMode_Source << qRgba(255, 0, 0, 127) << 127; + QTest::newRow("ARGB_PM source RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied + << QPainter::CompositionMode_Source << qRgba(127, 0, 0, 127) << 127; + QTest::newRow("ARGB source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32 + << QPainter::CompositionMode_SourceIn << qRgba(255, 0, 0, 127) << 127; + QTest::newRow("ARGB_PM source-in RGB30") << QImage::Format_RGB30 << QImage::Format_ARGB32_Premultiplied + << QPainter::CompositionMode_SourceIn << qRgba(127, 0, 0, 127) << 127; } void tst_QPainter::blendARGBonRGB() diff --git a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp index 13b15d09dd..1327cff1bd 100644 --- a/tests/auto/gui/painting/qtransform/tst_qtransform.cpp +++ b/tests/auto/gui/painting/qtransform/tst_qtransform.cpp @@ -57,6 +57,7 @@ private slots: void mapRect(); void assignments(); void mapToPolygon(); + void qhash(); void translate(); void scale(); void matrix(); @@ -361,6 +362,22 @@ void tst_QTransform::mapToPolygon() QVERIFY(equal); } +void tst_QTransform::qhash() +{ + QMatrix m1; + m1.shear(3.0, 2.0); + m1.rotate(44); + + QMatrix m2 = m1; + + QTransform t1(m1); + QTransform t2(m2); + + // not really much to test here, so just the bare minimum: + QCOMPARE(qHash(m1), qHash(m2)); + QCOMPARE(qHash(t1), qHash(t2)); +} + void tst_QTransform::translate() { diff --git a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp index 8f0d306cba..f6bd09958e 100644 --- a/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp +++ b/tests/auto/gui/text/qtextdocumentfragment/tst_qtextdocumentfragment.cpp @@ -1378,8 +1378,8 @@ void tst_QTextDocumentFragment::html_listStart1() { // don't create a block for the <ul> element, even if there's some whitespace between // it and the <li> - const char html[] = "<ul> <li>list item</li><ul>"; - cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0])))); + const QString html = QStringLiteral("<ul> <li>list item</li><ul>"); + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); QCOMPARE(doc->blockCount(), 1); } @@ -1387,8 +1387,8 @@ void tst_QTextDocumentFragment::html_listStart1() void tst_QTextDocumentFragment::html_listStart2() { // unlike with html_listStart1 we want a block showing the 'buggy' text here - const char html[] = "<ul>buggy, but text should appear<li>list item</li><ul>"; - cursor.insertFragment(QTextDocumentFragment::fromHtml(QByteArray::fromRawData(html, sizeof(html) / sizeof(html[0])))); + const QString html = QStringLiteral("<ul>buggy, but text should appear<li>list item</li><ul>"); + cursor.insertFragment(QTextDocumentFragment::fromHtml(html)); QCOMPARE(doc->blockCount(), 2); } diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index c63cfaf6b6..dcb3df834d 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -121,6 +121,14 @@ class tst_QNetworkReply: public QObject return s; }; + static QString tempRedirectReplyStr() { + QString s = "HTTP/1.1 307 Temporary Redirect\r\n" + "Content-Type: text/plain\r\n" + "location: %1\r\n" + "\r\n"; + return s; + }; + QEventLoop *loop; enum RunSimpleRequestReturn { Timeout = 0, Success, Failure }; int returnCode; @@ -456,6 +464,11 @@ private Q_SLOTS: void putWithRateLimiting(); + void ioHttpSingleRedirect(); + void ioHttpChangeMaxRedirects(); + void ioHttpRedirectErrors_data(); + void ioHttpRedirectErrors(); + // NOTE: This test must be last! void parentingRepliesToTheApp(); private: @@ -593,10 +606,16 @@ protected: virtual void reply() { Q_ASSERT(!client.isNull()); // we need to emulate the bytesWrittenSlot call if the data is empty. - if (dataToTransmit.size() == 0) + if (dataToTransmit.size() == 0) { QMetaObject::invokeMethod(this, "bytesWrittenSlot", Qt::QueuedConnection); - else + } else { client->write(dataToTransmit); + // FIXME: For SSL connections, if we don't flush the socket, the + // client never receives the data and since we're doing a disconnect + // immediately afterwards, it causes a RemoteHostClosedError for the + // client + client->flush(); + } } private: void connectSocketSignals() @@ -7962,7 +7981,142 @@ void tst_QNetworkReply::putWithRateLimiting() QCOMPARE(uploadedData, data); } +void tst_QNetworkReply::ioHttpSingleRedirect() +{ + QUrl localhost = QUrl("http://localhost"); + QByteArray http200Reply = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"; + + // Setup server to which the second server will redirect to + MiniHttpServer server2(http200Reply); + + QUrl redirectUrl = QUrl(localhost); + redirectUrl.setPort(server2.serverPort()); + + QByteArray tempRedirectReply = + tempRedirectReplyStr().arg(QString(redirectUrl.toEncoded())).toLatin1(); + + + // Setup redirect server + MiniHttpServer server(tempRedirectReply); + + localhost.setPort(server.serverPort()); + QNetworkRequest request(localhost); + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + + QNetworkReplyPtr reply(manager.get(request)); + QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl))); + QSignalSpy finSpy(reply.data(), SIGNAL(finished())); + + QVERIFY2(waitForFinish(reply) == Success, msgWaitForFinished(reply)); + + // Redirected and finished should be emitted exactly once + QCOMPARE(redSpy.count(), 1); + QCOMPARE(finSpy.count(), 1); + + // Original URL should not be changed after redirect + QCOMPARE(request.url(), localhost); + + // Verify Redirect url + QList<QVariant> args = redSpy.takeFirst(); + QCOMPARE(args.at(0).toUrl(), redirectUrl); + + // Reply url is set to the redirect url + QCOMPARE(reply->url(), redirectUrl); + QCOMPARE(reply->error(), QNetworkReply::NoError); +} + +void tst_QNetworkReply::ioHttpChangeMaxRedirects() +{ + QUrl localhost = QUrl("http://localhost"); + QByteArray http200Reply = "HTTP/1.1 200 OK\r\nContent-Length: 0\r\n\r\n"; + + MiniHttpServer server1(""); + MiniHttpServer server2(""); + MiniHttpServer server3(http200Reply); + + QUrl server2Url(localhost); + server2Url.setPort(server2.serverPort()); + server1.setDataToTransmit(tempRedirectReplyStr().arg( + QString(server2Url.toEncoded())).toLatin1()); + + QUrl server3Url(localhost); + server3Url.setPort(server3.serverPort()); + server2.setDataToTransmit(tempRedirectReplyStr().arg( + QString(server3Url.toEncoded())).toLatin1()); + + localhost.setPort(server1.serverPort()); + QNetworkRequest request(localhost); + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + + // Set Max redirects to 1. This will cause TooManyRedirectsError + request.setMaximumRedirectsAllowed(1); + + QNetworkReplyPtr reply(manager.get(request)); + QSignalSpy redSpy(reply.data(), SIGNAL(redirected(QUrl))); + QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + + QVERIFY(waitForFinish(reply) == Failure); + + QCOMPARE(redSpy.count(), request.maximumRedirectsAllowed()); + QCOMPARE(spy.count(), 1); + QVERIFY(reply->error() == QNetworkReply::TooManyRedirectsError); + + // Increase max redirects to allow successful completion + request.setMaximumRedirectsAllowed(3); + + QNetworkReplyPtr reply2(manager.get(request)); + QSignalSpy redSpy2(reply2.data(), SIGNAL(redirected(QUrl))); + + QVERIFY2(waitForFinish(reply2) == Success, msgWaitForFinished(reply2)); + + QCOMPARE(redSpy2.count(), 2); + QCOMPARE(reply2->url(), server3Url); + QVERIFY(reply2->error() == QNetworkReply::NoError); +} + +void tst_QNetworkReply::ioHttpRedirectErrors_data() +{ + QTest::addColumn<QString>("url"); + QTest::addColumn<QString>("dataToSend"); + QTest::addColumn<QNetworkReply::NetworkError>("error"); + + QString tempRedirectReply = QString("HTTP/1.1 307 Temporary Redirect\r\n" + "Content-Type: text/plain\r\n" + "location: http://localhost:%1\r\n\r\n"); + + QTest::newRow("too-many-redirects") << "http://localhost" << tempRedirectReply << QNetworkReply::TooManyRedirectsError; + QTest::newRow("insecure-redirect") << "https://localhost" << tempRedirectReply << QNetworkReply::InsecureRedirectError; + QTest::newRow("unknown-redirect") << "http://localhost"<< tempRedirectReply.replace("http", "bad_protocol") << QNetworkReply::ProtocolUnknownError; +} + +void tst_QNetworkReply::ioHttpRedirectErrors() +{ + QFETCH(QString, url); + QFETCH(QString, dataToSend); + QFETCH(QNetworkReply::NetworkError, error); + + QUrl localhost(url); + MiniHttpServer server("", localhost.scheme() == "https"); + + localhost.setPort(server.serverPort()); + + QByteArray d2s = dataToSend.arg( + QString::number(server.serverPort())).toLatin1(); + server.setDataToTransmit(d2s); + + QNetworkRequest request(localhost); + request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + QNetworkReplyPtr reply(manager.get(request)); + if (localhost.scheme() == "https") + reply.data()->ignoreSslErrors(); + QSignalSpy spy(reply.data(), SIGNAL(error(QNetworkReply::NetworkError))); + + QVERIFY(waitForFinish(reply) == Failure); + + QCOMPARE(spy.count(), 1); + QVERIFY(reply->error() == error); +} // NOTE: This test must be last testcase in tst_qnetworkreply! void tst_QNetworkReply::parentingRepliesToTheApp() diff --git a/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp b/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp index 76c36831bd..1c79b6c016 100644 --- a/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp +++ b/tests/auto/network/socket/qabstractsocket/tst_qabstractsocket.cpp @@ -37,11 +37,6 @@ #include <qcoreapplication.h> #include <qdebug.h> #include <qabstractsocket.h> -#include <qtcpserver.h> -#include <qtcpsocket.h> -#ifndef QT_NO_SSL -#include <qsslsocket.h> -#endif class tst_QAbstractSocket : public QObject { @@ -52,9 +47,7 @@ public: virtual ~tst_QAbstractSocket(); private slots: - void initTestCase(); void getSetCheck(); - void serverDisconnectWithBuffered(); }; tst_QAbstractSocket::tst_QAbstractSocket() @@ -73,11 +66,6 @@ public: void setPeerPort(quint16 port) { QAbstractSocket::setPeerPort(port); } }; -void tst_QAbstractSocket::initTestCase() -{ - qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState"); -} - // Testing get/set functions void tst_QAbstractSocket::getSetCheck() { @@ -106,46 +94,5 @@ void tst_QAbstractSocket::getSetCheck() QCOMPARE(quint16(0xffff), obj1.peerPort()); } -// Test buffered socket being properly closed on remote disconnect -void tst_QAbstractSocket::serverDisconnectWithBuffered() -{ - QTcpServer tcpServer; -#ifndef QT_NO_SSL - QSslSocket testSocket; -#else - QTcpSocket testSocket; -#endif - - QVERIFY(tcpServer.listen(QHostAddress::LocalHost)); - testSocket.connectToHost(tcpServer.serverAddress(), tcpServer.serverPort()); - // Accept connection on server side - QVERIFY(tcpServer.waitForNewConnection(5000)); - QTcpSocket *newConnection = tcpServer.nextPendingConnection(); - // Send one char and drop link - QVERIFY(newConnection != NULL); - QVERIFY(newConnection->putChar(0)); - QVERIFY(newConnection->flush()); - delete newConnection; - - QVERIFY(testSocket.waitForConnected(5000)); // ready for write - QVERIFY(testSocket.state() == QAbstractSocket::ConnectedState); - - QSignalSpy spyStateChanged(&testSocket, SIGNAL(stateChanged(QAbstractSocket::SocketState))); - QSignalSpy spyDisconnected(&testSocket, SIGNAL(disconnected())); - - QVERIFY(testSocket.waitForReadyRead(5000)); // have one char already in internal buffer - char buf[128]; - QCOMPARE(testSocket.read(buf, sizeof(buf)), Q_INT64_C(1)); - if (testSocket.state() != QAbstractSocket::UnconnectedState) { - QVERIFY(testSocket.waitForDisconnected(5000)); - QVERIFY(testSocket.state() == QAbstractSocket::UnconnectedState); - } - // Test signal emitting - QVERIFY(spyDisconnected.count() == 1); - QVERIFY(spyStateChanged.count() > 0); - QVERIFY(qvariant_cast<QAbstractSocket::SocketState>(spyStateChanged.last().first()) - == QAbstractSocket::UnconnectedState); -} - QTEST_MAIN(tst_QAbstractSocket) #include "tst_qabstractsocket.moc" diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 0ba9b6a58c..109e48ed74 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -200,6 +200,7 @@ private slots: void setSocketOption(); void clientSendDataOnDelayedDisconnect(); + void serverDisconnectWithBuffered(); protected slots: void nonBlockingIMAP_hostFound(); @@ -2984,5 +2985,50 @@ void tst_QTcpSocket::clientSendDataOnDelayedDisconnect() delete socket; } +// Test buffered socket being properly closed on remote disconnect +void tst_QTcpSocket::serverDisconnectWithBuffered() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState"); + + QTcpServer tcpServer; + QTcpSocket *socket = newSocket(); + + QVERIFY(tcpServer.listen(QHostAddress::LocalHost)); + socket->connectToHost(tcpServer.serverAddress(), tcpServer.serverPort()); + // Accept connection on server side + QVERIFY(tcpServer.waitForNewConnection(5000)); + QTcpSocket *newConnection = tcpServer.nextPendingConnection(); + // Send one char and drop link + QVERIFY(newConnection != NULL); + QVERIFY(newConnection->putChar(0)); + QVERIFY(newConnection->flush()); + delete newConnection; + + QVERIFY(socket->waitForConnected(5000)); // ready for write + QVERIFY(socket->state() == QAbstractSocket::ConnectedState); + + QSignalSpy spyStateChanged(socket, SIGNAL(stateChanged(QAbstractSocket::SocketState))); + QSignalSpy spyDisconnected(socket, SIGNAL(disconnected())); + + QVERIFY(socket->waitForReadyRead(5000)); // have one char already in internal buffer + char buf[128]; + QCOMPARE(socket->read(buf, sizeof(buf)), Q_INT64_C(1)); + if (socket->state() != QAbstractSocket::UnconnectedState) { + QVERIFY(socket->waitForDisconnected(5000)); + QVERIFY(socket->state() == QAbstractSocket::UnconnectedState); + } + // Test signal emitting + QVERIFY(spyDisconnected.count() == 1); + QVERIFY(spyStateChanged.count() > 0); + QVERIFY(qvariant_cast<QAbstractSocket::SocketState>(spyStateChanged.last().first()) + == QAbstractSocket::UnconnectedState); + + delete socket; +} + QTEST_MAIN(tst_QTcpSocket) #include "tst_qtcpsocket.moc" diff --git a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp index f4d3555531..d95f2fa546 100644 --- a/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp +++ b/tests/auto/network/ssl/qsslsocket/tst_qsslsocket.cpp @@ -170,6 +170,9 @@ private slots: void protocol(); void protocolServerSide_data(); void protocolServerSide(); +#ifndef QT_NO_OPENSSL + void serverCipherPreferences(); +#endif // QT_NO_OPENSSL void setCaCertificates(); void setLocalCertificate(); void localCertificateChain(); @@ -1063,6 +1066,7 @@ public: const QString &certFile = SRCDIR "certs/fluke.cert", const QString &interFile = QString()) : socket(0), + config(QSslConfiguration::defaultConfiguration()), ignoreSslErrors(true), peerVerifyMode(QSslSocket::AutoVerifyPeer), protocol(QSsl::TlsV1_0), @@ -1071,6 +1075,7 @@ public: m_interFile(interFile) { } QSslSocket *socket; + QSslConfiguration config; QString addCaCertificates; bool ignoreSslErrors; QSslSocket::PeerVerifyMode peerVerifyMode; @@ -1084,6 +1089,7 @@ protected: void incomingConnection(qintptr socketDescriptor) { socket = new QSslSocket(this); + socket->setSslConfiguration(config); socket->setPeerVerifyMode(peerVerifyMode); socket->setProtocol(protocol); if (ignoreSslErrors) @@ -1254,6 +1260,78 @@ void tst_QSslSocket::protocolServerSide() QCOMPARE(client->isEncrypted(), works); } +#ifndef QT_NO_OPENSSL + +void tst_QSslSocket::serverCipherPreferences() +{ + if (!QSslSocket::supportsSsl()) { + qWarning("SSL not supported, skipping test"); + return; + } + + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + // First using the default (server preference) + { + SslServer server; + server.ciphers = QString("AES128-SHA:AES256-SHA"); + QVERIFY(server.listen()); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + + QSslSocketPtr client(new QSslSocket); + socket = client.data(); + socket->setCiphers("AES256-SHA:AES128-SHA"); + + // upon SSL wrong version error, error will be triggered, not sslErrors + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); + connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit())); + + client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + loop.exec(); + + QVERIFY(client->isEncrypted()); + QCOMPARE(client->sessionCipher().name(), QString("AES128-SHA")); + } + + { + // Now using the client preferences + SslServer server; + QSslConfiguration config = QSslConfiguration::defaultConfiguration(); + config.setSslOption(QSsl::SslOptionDisableServerCipherPreference, true); + server.config = config; + server.ciphers = QString("AES128-SHA:AES256-SHA"); + QVERIFY(server.listen()); + + QEventLoop loop; + QTimer::singleShot(5000, &loop, SLOT(quit())); + + QSslSocketPtr client(new QSslSocket); + socket = client.data(); + socket->setCiphers("AES256-SHA:AES128-SHA"); + + // upon SSL wrong version error, error will be triggered, not sslErrors + connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), &loop, SLOT(quit())); + connect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(ignoreErrorSlot())); + connect(socket, SIGNAL(encrypted()), &loop, SLOT(quit())); + + client->connectToHostEncrypted(QHostAddress(QHostAddress::LocalHost).toString(), server.serverPort()); + + loop.exec(); + + QVERIFY(client->isEncrypted()); + QCOMPARE(client->sessionCipher().name(), QString("AES256-SHA")); + } +} + +#endif // QT_NO_OPENSSL + + void tst_QSslSocket::setCaCertificates() { if (!QSslSocket::supportsSsl()) @@ -2354,28 +2432,28 @@ void tst_QSslSocket::sslOptions() #ifdef SSL_OP_NO_COMPRESSION QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols, QSslConfigurationPrivate::defaultSslOptions), - long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION)); + long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_COMPRESSION|SSL_OP_CIPHER_SERVER_PREFERENCE)); #else QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols, QSslConfigurationPrivate::defaultSslOptions), - long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3)); + long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_CIPHER_SERVER_PREFERENCE)); #endif QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols, QSsl::SslOptionDisableEmptyFragments |QSsl::SslOptionDisableLegacyRenegotiation), - long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3)); + long(SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_CIPHER_SERVER_PREFERENCE)); #ifdef SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols, QSsl::SslOptionDisableEmptyFragments), - long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION))); + long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION|SSL_OP_CIPHER_SERVER_PREFERENCE))); #endif #ifdef SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS QCOMPARE(QSslSocketBackendPrivate::setupOpenSslOptions(QSsl::SecureProtocols, QSsl::SslOptionDisableLegacyRenegotiation), - long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3) & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)); + long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_CIPHER_SERVER_PREFERENCE) & ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)); #endif #ifdef SSL_OP_NO_TICKET @@ -2383,7 +2461,7 @@ void tst_QSslSocket::sslOptions() QSsl::SslOptionDisableEmptyFragments |QSsl::SslOptionDisableLegacyRenegotiation |QSsl::SslOptionDisableSessionTickets), - long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET))); + long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET|SSL_OP_CIPHER_SERVER_PREFERENCE))); #endif #ifdef SSL_OP_NO_TICKET @@ -2393,7 +2471,7 @@ void tst_QSslSocket::sslOptions() |QSsl::SslOptionDisableLegacyRenegotiation |QSsl::SslOptionDisableSessionTickets |QSsl::SslOptionDisableCompression), - long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET|SSL_OP_NO_COMPRESSION))); + long((SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TICKET|SSL_OP_NO_COMPRESSION|SSL_OP_CIPHER_SERVER_PREFERENCE))); #endif #endif } diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 8061b1ccb9..92a8623a64 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -162,16 +162,6 @@ static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface, return true; } -static inline int indexOfChild(QAccessibleInterface *parentInterface, QWidget *childWidget) -{ - if (!parentInterface || !childWidget) - return -1; - QAccessibleInterface *childInterface(QAccessible::queryAccessibleInterface(childWidget)); - if (!childInterface) - return -1; - return parentInterface->indexOfChild(childInterface); -} - #define EXPECT(cond) \ do { \ if (!errorAt && !(cond)) { \ diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index 488b65c657..a5840d16d2 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -566,7 +566,9 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge #endif QProcess proc; - static const QProcessEnvironment environment = processEnvironment(); + QProcessEnvironment environment = processEnvironment(); + if (crashes) + environment.insert("QTEST_DISABLE_STACK_DUMP", "1"); proc.setProcessEnvironment(environment); const QString path = subdir + QLatin1Char('/') + subdir; proc.start(path, arguments); diff --git a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp index 5e00ca9450..11d41d9b20 100644 --- a/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp +++ b/tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp @@ -6010,10 +6010,13 @@ void tst_QWidget::childEvents() expected = EventRecorder::EventList() << qMakePair(&widget, QEvent::Polish) + << qMakePair(&widget, QEvent::PlatformSurface) << qMakePair(&widget, QEvent::WinIdChange) + << qMakePair(&widget, QEvent::WindowIconChange) << qMakePair(&widget, QEvent::Move) << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show) + << qMakePair(&widget, QEvent::CursorChange) << qMakePair(&widget, QEvent::ShowToParent); QVERIFY2(spy.eventList() == expected, @@ -6025,13 +6028,9 @@ void tst_QWidget::childEvents() EventRecorder::EventList() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) -#if defined(Q_OS_OSX) || defined(Q_OS_QNX) << qMakePair(&widget, QEvent::UpdateLater) -#endif << qMakePair(&widget, QEvent::UpdateRequest); - if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) - QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue); QVERIFY2(spy.eventList() == expected, EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData()); } @@ -6100,10 +6099,13 @@ void tst_QWidget::childEvents() << qMakePair(&widget, QEvent::Polish) << qMakePair(&widget, QEvent::ChildPolished) << qMakePair(&widget, QEvent::ChildPolished) + << qMakePair(&widget, QEvent::PlatformSurface) << qMakePair(&widget, QEvent::WinIdChange) + << qMakePair(&widget, QEvent::WindowIconChange) << qMakePair(&widget, QEvent::Move) << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show) + << qMakePair(&widget, QEvent::CursorChange) << qMakePair(&widget, QEvent::ShowToParent); QVERIFY2(spy.eventList() == expected, @@ -6116,13 +6118,9 @@ void tst_QWidget::childEvents() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)) -#if defined(Q_OS_OSX) || defined(Q_OS_QNX) << qMakePair(&widget, QEvent::UpdateLater) -#endif << qMakePair(&widget, QEvent::UpdateRequest); - if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) - QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue); QVERIFY2(spy.eventList() == expected, EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData()); } @@ -6193,10 +6191,13 @@ void tst_QWidget::childEvents() EventRecorder::EventList() << qMakePair(&widget, QEvent::Polish) << qMakePair(&widget, QEvent::ChildPolished) + << qMakePair(&widget, QEvent::PlatformSurface) << qMakePair(&widget, QEvent::WinIdChange) + << qMakePair(&widget, QEvent::WindowIconChange) << qMakePair(&widget, QEvent::Move) << qMakePair(&widget, QEvent::Resize) << qMakePair(&widget, QEvent::Show) + << qMakePair(&widget, QEvent::CursorChange) << qMakePair(&widget, QEvent::ShowToParent); QVERIFY2(spy.eventList() == expected, @@ -6209,13 +6210,9 @@ void tst_QWidget::childEvents() << qMakePair(&widget, QEvent::PolishRequest) << qMakePair(&widget, QEvent::Type(QEvent::User + 1)) << qMakePair(&widget, QEvent::Type(QEvent::User + 2)) -#if defined(Q_OS_OSX) || defined(Q_OS_QNX) << qMakePair(&widget, QEvent::UpdateLater) -#endif << qMakePair(&widget, QEvent::UpdateRequest); - if (m_platform == QStringLiteral("windows") || m_platform == QStringLiteral("xcb")) - QEXPECT_FAIL("", EventRecorder::msgExpectFailQtBug26424(expected, spy.eventList()).constData(), Continue); QVERIFY2(spy.eventList() == expected, EventRecorder::msgEventListMismatch(expected, spy.eventList()).constData()); } diff --git a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp index 148c2352a5..4bdb299213 100644 --- a/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp +++ b/tests/auto/widgets/kernel/qwidget_window/tst_qwidget_window.cpp @@ -97,6 +97,8 @@ private slots: void tst_resize_count(); void tst_move_count(); + + void tst_eventfilter_on_toplevel(); }; void tst_QWidget_window::initTestCase() @@ -762,5 +764,48 @@ void tst_QWidget_window::tst_move_count() QTRY_VERIFY(move.moveCount >= 1); } +class EventFilter : public QObject +{ +public: + int eventCount; + + EventFilter() + : QObject(), + eventCount(0) + { + } + + static QEvent::Type filterEventType() + { + static int type = QEvent::registerEventType(); + return static_cast<QEvent::Type>(type); + } + +protected: + bool eventFilter(QObject *o, QEvent *e) Q_DECL_OVERRIDE + { + if (e->type() == filterEventType()) + ++eventCount; + + return QObject::eventFilter(o, e); + } +}; + +void tst_QWidget_window::tst_eventfilter_on_toplevel() +{ + QWidget w; + EventFilter filter; + w.installEventFilter(&filter); + w.show(); + QVERIFY(QTest::qWaitForWindowActive(&w)); + QVERIFY(w.isWindow()); + QCOMPARE(filter.eventCount, 0); + + // send an event not handled in a special way by QWidgetWindow::event, + // and check that it's received by the event filter + QCoreApplication::postEvent(w.windowHandle(), new QEvent(EventFilter::filterEventType())); + QTRY_COMPARE(filter.eventCount, 1); +} + QTEST_MAIN(tst_QWidget_window) #include "tst_qwidget_window.moc" diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_0_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_1_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png Binary files differindex a75833c89c..00447760ec 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_raised_2_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_0_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_1_2.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_0.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_1.png diff --git a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png Binary files differindex d656ac56f0..4c809a2c80 100644 --- a/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png +++ b/tests/auto/widgets/widgets/qframe/images/winpanel_sunken_2_2.png diff --git a/tests/benchmarks/corelib/tools/qringbuffer/main.cpp b/tests/benchmarks/corelib/tools/qringbuffer/main.cpp index 6bb82a8056..cf55aeaee5 100644 --- a/tests/benchmarks/corelib/tools/qringbuffer/main.cpp +++ b/tests/benchmarks/corelib/tools/qringbuffer/main.cpp @@ -48,10 +48,10 @@ void tst_qringbuffer::reserveAndRead() { QRingBuffer ringBuffer; QBENCHMARK { - for (int i = 1; i < 256; ++i) + for (qint64 i = 1; i < 256; ++i) ringBuffer.reserve(i); - for (int i = 1; i < 256; ++i) + for (qint64 i = 1; i < 256; ++i) ringBuffer.read(0, i); } } diff --git a/tests/manual/cocoa/qt_on_cocoa/main.mm b/tests/manual/cocoa/qt_on_cocoa/main.mm index 5dd546479e..23370b0305 100644 --- a/tests/manual/cocoa/qt_on_cocoa/main.mm +++ b/tests/manual/cocoa/qt_on_cocoa/main.mm @@ -31,123 +31,35 @@ ** ****************************************************************************/ -#include <QtGui> -#include <QtDeclarative> +#include "rasterwindow.h" +#include <QtGui> #include <QtWidgets/QtWidgets> -#include <private/qwidgetwindow_p.h> -#include <QtGui/qpa/qplatformnativeinterface.h> - -#include <QtGui/QPixmap> - -#include "window.h" #include <Cocoa/Cocoa.h> - -@interface FilledView : NSView -{ - +@interface AppDelegate : NSObject <NSApplicationDelegate> { + QGuiApplication *m_app; + QWindow *m_window; } +- (AppDelegate *) initWithArgc:(int)argc argv:(const char **)argv; +- (void) applicationWillFinishLaunching: (NSNotification *)notification; +- (void)applicationWillTerminate:(NSNotification *)notification; @end -@implementation FilledView - -- (void)drawRect:(NSRect)dirtyRect { - // set any NSColor for filling, say white: - [[NSColor redColor] setFill]; - NSRectFill(dirtyRect); -} - -@end - -@interface QtMacToolbarDelegate : NSObject <NSToolbarDelegate> +@implementation AppDelegate +- (AppDelegate *) initWithArgc:(int)argc argv:(const char **)argv { -@public - NSToolbar *toolbar; -} - -- (id)init; -- (NSToolbarItem *) toolbar: (NSToolbar *)toolbar itemForItemIdentifier: (NSString *) itemIdent willBeInsertedIntoToolbar:(BOOL) willBeInserted; -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)tb; -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)toolbar; -- (NSArray *)toolbarSelectableItemIdentifiers:(NSToolbar *)toolbar; -@end - -@implementation QtMacToolbarDelegate - -- (id)init -{ - self = [super init]; - if (self) { - } + m_app = new QGuiApplication(argc, const_cast<char **>(argv)); return self; } -- (void)dealloc -{ - [super dealloc]; -} - -- (NSArray *)toolbarDefaultItemIdentifiers:(NSToolbar*)tb -{ - Q_UNUSED(tb); - NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; -// [array addObject : NSToolbarPrintItemIdentifier]; -// [array addObject : NSToolbarShowColorsItemIdentifier]; - [array addObject : @"filledView"]; - return array; -} - -- (NSArray *)toolbarAllowedItemIdentifiers:(NSToolbar*)tb -{ - Q_UNUSED(tb); - NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; -// [array addObject : NSToolbarPrintItemIdentifier]; -// [array addObject : NSToolbarShowColorsItemIdentifier]; - [array addObject : @"filledView"]; - return array; -} - -- (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)tb -{ - Q_UNUSED(tb); - NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; - return array; -} - -- (IBAction)itemClicked:(id)sender +- (void) applicationWillFinishLaunching: (NSNotification *)notification { + Q_UNUSED(notification); -} - -- (NSToolbarItem *) toolbar: (NSToolbar *)tb itemForItemIdentifier: (NSString *) itemIdentifier willBeInsertedIntoToolbar:(BOOL) willBeInserted -{ - Q_UNUSED(tb); - Q_UNUSED(willBeInserted); - //const QString identifier = toQString(itemIdentifier); - //NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease]; - //return toolbarItem; - - //NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease]; - NSToolbarItem *toolbarItem = [[[NSToolbarItem alloc] initWithItemIdentifier: itemIdentifier] autorelease]; - FilledView *theView = [[FilledView alloc] init]; - [toolbarItem setView : theView]; - [toolbarItem setMinSize : NSMakeSize(400, 40)]; - [toolbarItem setMaxSize : NSMakeSize(4000, 40)]; - return toolbarItem; -} -@end - -@interface WindowAndViewAndQtCreator : NSObject {} -- (void)createWindowAndViewAndQt; -@end - -@implementation WindowAndViewAndQtCreator -- (void)createWindowAndViewAndQt { - - // Create the window + // Create the NSWindow NSRect frame = NSMakeRect(500, 500, 500, 500); NSWindow* window = [[NSWindow alloc] initWithContentRect:frame styleMask:NSTitledWindowMask | NSClosableWindowMask | NSMiniaturizableWindowMask | NSResizableWindowMask @@ -156,49 +68,31 @@ NSString *title = @"This the NSWindow window"; [window setTitle:title]; - [window setBackgroundColor:[NSColor blueColor]]; - // Create a tool bar, set Qt delegate - NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier : @"foobartoolbar"]; - QtMacToolbarDelegate *delegate = [[QtMacToolbarDelegate alloc] init]; - [toolbar setDelegate : delegate]; - [window setToolbar : toolbar]; - - // Create the QWindow, don't show it. - Window *qtWindow = new Window(); - qtWindow->create(); - - //QSGView *qtWindow = new QSGView(); - //qtWindow->setSource(QUrl::fromLocalFile("/Users/msorvig/code/qt5/qtdeclarative/examples/declarative/samegame/samegame.qml")); - // qtWindow->setWindowFlags(Qt::WindowType(13)); // 13: NativeEmbeddedWindow - - // Get the nsview from the QWindow, set it as the content view - // on the NSWindow created above. - QPlatformNativeInterface *platformNativeInterface = QGuiApplication::platformNativeInterface(); - NSView *qtView = (NSView *)platformNativeInterface->nativeResourceForWindow("nsview", qtWindow); - [window setContentView:qtView]; + // Create the QWindow, use its NSView as the content view + m_window = new RasterWindow(); + [window setContentView:reinterpret_cast<NSView *>(m_window->winId())]; + + // Show the NSWindow [window makeKeyAndOrderFront:NSApp]; } -@end -int main(int argc, char *argv[]) +- (void)applicationWillTerminate:(NSNotification *)notification { - QGuiApplication app(argc, argv); - - // fake NSApplicationMain() implementation follows: - NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; - [NSApplication sharedApplication]; + Q_UNUSED(notification); + delete m_window; + delete m_app; +} - // schedule call to create the UI. - WindowAndViewAndQtCreator *windowAndViewAndQtCreator= [WindowAndViewAndQtCreator alloc]; - [NSTimer scheduledTimerWithTimeInterval:0 target:windowAndViewAndQtCreator selector:@selector(createWindowAndViewAndQt) userInfo:nil repeats:NO]; +@end - [(NSApplication *)NSApp run]; - [NSApp release]; - [pool release]; - exit(0); - return 0; +int main(int argc, const char *argv[]) +{ + // Create NSApplicaiton with delgate + NSApplication *app =[NSApplication sharedApplication]; + app.delegate = [[AppDelegate alloc] initWithArgc:argc argv:argv]; + return NSApplicationMain (argc, argv); } diff --git a/tests/manual/cocoa/qt_on_cocoa/qt_on_cocoa.pro b/tests/manual/cocoa/qt_on_cocoa/qt_on_cocoa.pro index 3d526909a5..97e4473e15 100644 --- a/tests/manual/cocoa/qt_on_cocoa/qt_on_cocoa.pro +++ b/tests/manual/cocoa/qt_on_cocoa/qt_on_cocoa.pro @@ -1,13 +1,11 @@ TEMPLATE = app OBJECTIVE_SOURCES += main.mm -HEADERS += window.h -SOURCES += window.cpp +HEADERS += rasterwindow.h +SOURCES += rasterwindow.cpp LIBS += -framework Cocoa -QMAKE_INFO_PLIST = Info_mac.plist -OTHER_FILES = Info_mac.plist -QT += gui widgets widgets-private gui-private core-private +QT += gui widgets quick -QT += declarative +QT += quick DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0 diff --git a/tests/manual/cocoa/qt_on_cocoa/window.cpp b/tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp index 9929a50065..9b8f5e63ce 100644 --- a/tests/manual/cocoa/qt_on_cocoa/window.cpp +++ b/tests/manual/cocoa/qt_on_cocoa/rasterwindow.cpp @@ -31,9 +31,9 @@ ** ****************************************************************************/ -#include "window.h" +#include "rasterwindow.h" -#include <private/qguiapplication_p.h> +//#include <private/qguiapplication_p.h> #include <QBackingStore> #include <QPainter> @@ -48,21 +48,14 @@ QColor colorTable[] = QColor("#c0ef8f") }; -Window::Window(QScreen *screen) - : QWindow(screen) +RasterWindow::RasterWindow(QRasterWindow *parent) + : QRasterWindow(parent) , m_backgroundColorIndex(colorIndexId++) { initialize(); } -Window::Window(QWindow *parent) - : QWindow(parent) - , m_backgroundColorIndex(colorIndexId++) -{ - initialize(); -} - -void Window::initialize() +void RasterWindow::initialize() { if (parent()) setGeometry(QRect(160, 120, 320, 240)); @@ -85,12 +78,12 @@ void Window::initialize() m_renderTimer = 0; } -void Window::mousePressEvent(QMouseEvent *event) +void RasterWindow::mousePressEvent(QMouseEvent *event) { m_lastPos = event->pos(); } -void Window::mouseMoveEvent(QMouseEvent *event) +void RasterWindow::mouseMoveEvent(QMouseEvent *event) { if (m_lastPos != QPoint(-1, -1)) { QPainter p(&m_image); @@ -102,7 +95,7 @@ void Window::mouseMoveEvent(QMouseEvent *event) scheduleRender(); } -void Window::mouseReleaseEvent(QMouseEvent *event) +void RasterWindow::mouseReleaseEvent(QMouseEvent *event) { if (m_lastPos != QPoint(-1, -1)) { QPainter p(&m_image); @@ -114,16 +107,16 @@ void Window::mouseReleaseEvent(QMouseEvent *event) scheduleRender(); } -void Window::exposeEvent(QExposeEvent *) +void RasterWindow::exposeEvent(QExposeEvent *) { scheduleRender(); } -void Window::resizeEvent(QResizeEvent *) +void RasterWindow::resizeEvent(QResizeEvent *) { QImage old = m_image; - //qDebug() << "Window::resizeEvent" << width << height; + //qDebug() << "RasterWindow::resizeEvent" << width << height; int width = qMax(geometry().width(), old.width()); int height = qMax(geometry().height(), old.height()); @@ -139,7 +132,7 @@ void Window::resizeEvent(QResizeEvent *) render(); } -void Window::keyPressEvent(QKeyEvent *event) +void RasterWindow::keyPressEvent(QKeyEvent *event) { switch (event->key()) { case Qt::Key_Backspace: @@ -156,20 +149,20 @@ void Window::keyPressEvent(QKeyEvent *event) scheduleRender(); } -void Window::scheduleRender() +void RasterWindow::scheduleRender() { if (!m_renderTimer) m_renderTimer = startTimer(1); } -void Window::timerEvent(QTimerEvent *) +void RasterWindow::timerEvent(QTimerEvent *) { render(); killTimer(m_renderTimer); m_renderTimer = 0; } -void Window::render() +void RasterWindow::render() { QRect rect(QPoint(), geometry().size()); diff --git a/tests/manual/cocoa/qt_on_cocoa/window.h b/tests/manual/cocoa/qt_on_cocoa/rasterwindow.h index a36180e0f3..1de66b5302 100644 --- a/tests/manual/cocoa/qt_on_cocoa/window.h +++ b/tests/manual/cocoa/qt_on_cocoa/rasterwindow.h @@ -31,14 +31,13 @@ ** ****************************************************************************/ -#include <QWindow> +#include <QRasterWindow> #include <QImage> -class Window : public QWindow +class RasterWindow : public QRasterWindow { public: - Window(QWindow *parent = 0); - Window(QScreen *screen); + RasterWindow(QRasterWindow *parent = 0); protected: void mousePressEvent(QMouseEvent *); diff --git a/tests/manual/qscreen/propertywatcher.cpp b/tests/manual/qscreen/propertywatcher.cpp index cfb5ea272d..19668a8d26 100644 --- a/tests/manual/qscreen/propertywatcher.cpp +++ b/tests/manual/qscreen/propertywatcher.cpp @@ -50,6 +50,8 @@ PropertyWatcher::PropertyWatcher(QObject *subject, QString annotation, QWidget * if (prop.isReadable()) { PropertyField* field = new PropertyField(m_subject, prop); m_layout->addRow(prop.name(), field); + if (!qstrcmp(prop.name(), "name")) + setWindowIconText(prop.read(subject).toString()); } } QPushButton *updateButton = new QPushButton("update"); |