From 8ac686e9f4f20368ba5e2cfc8441c3d958980330 Mon Sep 17 00:00:00 2001 From: Ivan Solovev Date: Tue, 20 Jul 2021 12:59:10 +0200 Subject: QString: extend unit tests This patch introduces some test improvements to check the calls of different methods on an empty default-constructed string. Apart from that, some other tests are added to extend code coverage. As a drive-by: * fix int -> qsizetype in the test data * fix int -> enum in the test data Task-number: QTBUG-91736 Pick-to: 6.2 6.1 Change-Id: I159473b7f5dcbea1bdaf2966979e066296351208 Reviewed-by: Edward Welbourne Reviewed-by: Andrei Golubev --- tests/auto/corelib/text/qstring/tst_qstring.cpp | 569 +++++++++++++++++++++--- 1 file changed, 495 insertions(+), 74 deletions(-) diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp index 26d10244ae..10932405c8 100644 --- a/tests/auto/corelib/text/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp @@ -351,6 +351,7 @@ private slots: void check_QDataStream(); void fromRawData(); void setRawData(); + void setUnicode(); void endsWith(); void startsWith(); void setNum(); @@ -549,6 +550,7 @@ private slots: void toNum(); void localeAwareCompare_data(); void localeAwareCompare(); + void iterators(); void reverseIterators(); void split_data(); void split(); @@ -595,6 +597,12 @@ private slots: void isValidUtf16(); void unicodeStrings(); void vasprintfWithPrecision(); + + void rawData(); + void clear(); + void sliced(); + void chopped(); + void removeIf(); }; template const T &verifyZeroTermination(const T &t) { return t; } @@ -682,47 +690,30 @@ void tst_QString::indexOf3_data() indexOf2_data(); } -void tst_QString::length_data() -{ - QTest::addColumn("s1" ); - QTest::addColumn("res" ); - - QTest::newRow( "data0" ) << QString("Test") << 4; - QTest::newRow( "data1" ) << QString("The quick brown fox jumps over the lazy dog") << 43; - QTest::newRow( "data2" ) << QString() << 0; - QTest::newRow( "data3" ) << QString("A") << 1; - QTest::newRow( "data4" ) << QString("AB") << 2; - QTest::newRow( "data5" ) << QString("AB\n") << 3; - QTest::newRow( "data6" ) << QString("AB\nC") << 4; - QTest::newRow( "data7" ) << QString("\n") << 1; - QTest::newRow( "data8" ) << QString("\nA") << 2; - QTest::newRow( "data9" ) << QString("\nAB") << 3; - QTest::newRow( "data10" ) << QString("\nAB\nCDE") << 7; - QTest::newRow( "data11" ) << QString("shdnftrheid fhgnt gjvnfmd chfugkh bnfhg thgjf vnghturkf chfnguh bjgnfhvygh hnbhgutjfv dhdnjds dcjs d") << 100; -} - void tst_QString::replace_qchar_qchar_data() { QTest::addColumn("src" ); QTest::addColumn("before" ); QTest::addColumn("after" ); - QTest::addColumn("cs" ); + QTest::addColumn("cs"); QTest::addColumn("expected" ); - QTest::newRow( "1" ) << QString("foo") << QChar('o') << QChar('a') - << int(Qt::CaseSensitive) << QString("faa"); - QTest::newRow( "2" ) << QString("foo") << QChar('o') << QChar('a') - << int(Qt::CaseInsensitive) << QString("faa"); - QTest::newRow( "3" ) << QString("foo") << QChar('O') << QChar('a') - << int(Qt::CaseSensitive) << QString("foo"); - QTest::newRow( "4" ) << QString("foo") << QChar('O') << QChar('a') - << int(Qt::CaseInsensitive) << QString("faa"); - QTest::newRow( "5" ) << QString("ababABAB") << QChar('a') << QChar(' ') - << int(Qt::CaseSensitive) << QString(" b bABAB"); - QTest::newRow( "6" ) << QString("ababABAB") << QChar('a') << QChar(' ') - << int(Qt::CaseInsensitive) << QString(" b b B B"); - QTest::newRow( "7" ) << QString("ababABAB") << QChar() << QChar(' ') - << int(Qt::CaseInsensitive) << QString("ababABAB"); + QTest::newRow("1") << QString("foo") << QChar('o') << QChar('a') << Qt::CaseSensitive + << QString("faa"); + QTest::newRow("2") << QString("foo") << QChar('o') << QChar('a') << Qt::CaseInsensitive + << QString("faa"); + QTest::newRow("3") << QString("foo") << QChar('O') << QChar('a') << Qt::CaseSensitive + << QString("foo"); + QTest::newRow("4") << QString("foo") << QChar('O') << QChar('a') << Qt::CaseInsensitive + << QString("faa"); + QTest::newRow("5") << QString("ababABAB") << QChar('a') << QChar(' ') << Qt::CaseSensitive + << QString(" b bABAB"); + QTest::newRow("6") << QString("ababABAB") << QChar('a') << QChar(' ') << Qt::CaseInsensitive + << QString(" b b B B"); + QTest::newRow("7") << QString("ababABAB") << QChar() << QChar(' ') << Qt::CaseInsensitive + << QString("ababABAB"); + QTest::newRow("8") << QString() << QChar() << QChar('x') << Qt::CaseInsensitive << QString(); + QTest::newRow("9") << QString() << QChar('a') << QChar('x') << Qt::CaseInsensitive << QString(); } void tst_QString::replace_qchar_qchar() @@ -730,10 +721,10 @@ void tst_QString::replace_qchar_qchar() QFETCH(QString, src); QFETCH(QChar, before); QFETCH(QChar, after); - QFETCH(int, cs); + QFETCH(Qt::CaseSensitivity, cs); QFETCH(QString, expected); - QCOMPARE(src.replace(before, after, Qt::CaseSensitivity(cs)), expected); + QCOMPARE(src.replace(before, after, cs), expected); } void tst_QString::replace_qchar_qstring_data() @@ -741,25 +732,33 @@ void tst_QString::replace_qchar_qstring_data() QTest::addColumn("src" ); QTest::addColumn("before" ); QTest::addColumn("after" ); - QTest::addColumn("cs" ); + QTest::addColumn("cs"); QTest::addColumn("expected" ); - QTest::newRow( "1" ) << QString("foo") << QChar('o') << QString("aA") - << int(Qt::CaseSensitive) << QString("faAaA"); - QTest::newRow( "2" ) << QString("foo") << QChar('o') << QString("aA") - << int(Qt::CaseInsensitive) << QString("faAaA"); - QTest::newRow( "3" ) << QString("foo") << QChar('O') << QString("aA") - << int(Qt::CaseSensitive) << QString("foo"); - QTest::newRow( "4" ) << QString("foo") << QChar('O') << QString("aA") - << int(Qt::CaseInsensitive) << QString("faAaA"); - QTest::newRow( "5" ) << QString("ababABAB") << QChar('a') << QString(" ") - << int(Qt::CaseSensitive) << QString(" b bABAB"); - QTest::newRow( "6" ) << QString("ababABAB") << QChar('a') << QString(" ") - << int(Qt::CaseInsensitive) << QString(" b b B B"); - QTest::newRow( "7" ) << QString("ababABAB") << QChar() << QString(" ") - << int(Qt::CaseInsensitive) << QString("ababABAB"); - QTest::newRow( "8" ) << QString("ababABAB") << QChar() << QString() - << int(Qt::CaseInsensitive) << QString("ababABAB"); + QTest::newRow("1") << QString("foo") << QChar('o') << QString("aA") << Qt::CaseSensitive + << QString("faAaA"); + QTest::newRow("2") << QString("foo") << QChar('o') << QString("aA") << Qt::CaseInsensitive + << QString("faAaA"); + QTest::newRow("3") << QString("foo") << QChar('O') << QString("aA") << Qt::CaseSensitive + << QString("foo"); + QTest::newRow("4") << QString("foo") << QChar('O') << QString("aA") << Qt::CaseInsensitive + << QString("faAaA"); + QTest::newRow("5") << QString("ababABAB") << QChar('a') << QString(" ") << Qt::CaseSensitive + << QString(" b bABAB"); + QTest::newRow("6") << QString("ababABAB") << QChar('a') << QString(" ") << Qt::CaseInsensitive + << QString(" b b B B"); + QTest::newRow("7") << QString("ababABAB") << QChar() << QString(" ") << Qt::CaseInsensitive + << QString("ababABAB"); + QTest::newRow("8") << QString("ababABAB") << QChar() << QString() << Qt::CaseInsensitive + << QString("ababABAB"); + QTest::newRow("null-in-null-with-X") << QString() << QChar() << QString("X") + << Qt::CaseSensitive << QString(); + QTest::newRow("x-in-null-with-abc") << QString() << QChar('x') << QString("abc") + << Qt::CaseSensitive << QString(); + QTest::newRow("null-in-empty-with-X") << QString("") << QChar() << QString("X") + << Qt::CaseInsensitive << QString(); + QTest::newRow("x-in-empty-with-abc") << QString("") << QChar('x') << QString("abc") + << Qt::CaseInsensitive << QString(); } void tst_QString::replace_qchar_qstring() @@ -767,10 +766,10 @@ void tst_QString::replace_qchar_qstring() QFETCH(QString, src); QFETCH(QChar, before); QFETCH(QString, after); - QFETCH(int, cs); + QFETCH(Qt::CaseSensitivity, cs); QFETCH(QString, expected); - QCOMPARE(src.replace(before, after, Qt::CaseSensitivity(cs)), expected); + QCOMPARE(src.replace(before, after, cs), expected); } void tst_QString::replace_uint_uint_data() @@ -781,12 +780,20 @@ void tst_QString::replace_uint_uint_data() QTest::addColumn("after" ); QTest::addColumn("result" ); + QTest::newRow("empty_rem00") << QString() << 0 << 0 << QString("") << QString(); + QTest::newRow("empty_rem01") << QString() << 0 << 3 << QString("") << QString(); + QTest::newRow("empty_rem02") << QString() << 5 << 3 << QString("") << QString(); + QTest::newRow( "rem00" ) << QString("-<>ABCABCABCABC>") << 0 << 3 << QString("") << QString("ABCABCABCABC>"); QTest::newRow( "rem01" ) << QString("ABCABCABCABC>") << 1 << 4 << QString("") << QString("ACABCABC>"); QTest::newRow( "rem04" ) << QString("ACABCABC>") << 8 << 4 << QString("") << QString("ACABCABC"); QTest::newRow( "rem05" ) << QString("ACABCABC") << 7 << 1 << QString("") << QString("ACABCAB"); QTest::newRow( "rem06" ) << QString("ACABCAB") << 4 << 0 << QString("") << QString("ACABCAB"); + QTest::newRow("empty_rep00") << QString() << 0 << 0 << QString("X") << QString("X"); + QTest::newRow("empty_rep01") << QString() << 0 << 3 << QString("X") << QString("X"); + QTest::newRow("empty_rep02") << QString() << 5 << 3 << QString("X") << QString(); + QTest::newRow( "rep00" ) << QString("ACABCAB") << 4 << 0 << QString("X") << QString("ACABXCAB"); QTest::newRow( "rep01" ) << QString("ACABXCAB") << 4 << 1 << QString("Y") << QString("ACABYCAB"); QTest::newRow( "rep02" ) << QString("ACABYCAB") << 4 << 1 << QString("") << QString("ACABCAB"); @@ -860,6 +867,8 @@ void tst_QString::replace_string_data() QTest::newRow( "rep15" ) << QString("fooxbarxbazxblub") << QString("x") << QString("yz") << QString("fooyzbaryzbazyzblub") << true; QTest::newRow( "rep16" ) << QString("fooxbarxbazxblub") << QString("x") << QString("z") << QString("foozbarzbazzblub") << true; QTest::newRow( "rep17" ) << QString("fooxybarxybazxyblub") << QString("xy") << QString("z") << QString("foozbarzbazzblub") << true; + QTest::newRow("rep18") << QString() << QString() << QString("X") << QString("X") << false; + QTest::newRow("rep19") << QString() << QString("A") << QString("X") << QString("") << false; } void tst_QString::replace_regexp_data() @@ -880,6 +889,7 @@ void tst_QString::replace_regexp_data() QTest::newRow( "rep01" ) << QString("banana") << QString("^.a()") << QString("\\1") << QString("nana"); QTest::newRow( "rep02" ) << QString("banana") << QString("(ba)") << QString("\\1X\\1") << QString("baXbanana"); QTest::newRow( "rep03" ) << QString("banana") << QString("(ba)(na)na") << QString("\\2X\\1") << QString("naXba"); + QTest::newRow("rep04") << QString() << QString("(ba)") << QString("\\1X\\1") << QString(); QTest::newRow("backref00") << QString("\\1\\2\\3\\4\\5\\6\\7\\8\\9\\A\\10\\11") << QString("\\\\[34]") << QString("X") << QString("\\1\\2XX\\5\\6\\7\\8\\9\\A\\10\\11"); @@ -910,6 +920,9 @@ void tst_QString::utf8_data() QTest::addColumn("utf8" ); QTest::addColumn("res" ); + QTest::newRow("null") << QByteArray() << QString(); + QTest::newRow("empty") << QByteArray("") << QString(""); + QTest::newRow( "str0" ) << QByteArray("abcdefgh") << QString("abcdefgh"); QTest::newRow( "str1" ) << QByteArray("\303\266\303\244\303\274\303\226\303\204\303\234\303\270\303\246\303\245\303\230\303\206\303\205") @@ -939,10 +952,36 @@ void tst_QString::utf8_data() QTest::newRow("surrogate") << QByteArray("Old Italic: \360\220\214\200\360\220\214\201\360\220\214\202\360\220\214\203\360\220\214\204") << str; } +void tst_QString::length_data() +{ + QTest::addColumn("s1"); + QTest::addColumn("res"); + + QTest::newRow("null") << QString() << qsizetype(0); + QTest::newRow("empty") << QString("") << qsizetype(0); + QTest::newRow("data0") << QString("Test") << qsizetype(4); + QTest::newRow("data1") << QString("The quick brown fox jumps over the lazy dog") + << qsizetype(43); + QTest::newRow("data3") << QString("A") << qsizetype(1); + QTest::newRow("data4") << QString("AB") << qsizetype(2); + QTest::newRow("data5") << QString("AB\n") << qsizetype(3); + QTest::newRow("data6") << QString("AB\nC") << qsizetype(4); + QTest::newRow("data7") << QString("\n") << qsizetype(1); + QTest::newRow("data8") << QString("\nA") << qsizetype(2); + QTest::newRow("data9") << QString("\nAB") << qsizetype(3); + QTest::newRow("data10") << QString("\nAB\nCDE") << qsizetype(7); + QTest::newRow("data11") << QString("shdnftrheid fhgnt gjvnfmd chfugkh bnfhg thgjf vnghturkf " + "chfnguh bjgnfhvygh hnbhgutjfv dhdnjds dcjs d") + << qsizetype(100); +} + void tst_QString::length() { - QFETCH( QString, s1 ); - QTEST( (int)s1.length(), "res" ); + // size(), length() and count() do the same + QFETCH(QString, s1); + QTEST(s1.length(), "res"); + QTEST(s1.size(), "res"); + QTEST(s1.count(), "res"); } #include @@ -1045,6 +1084,7 @@ void tst_QString::isNull() { QString a; QVERIFY(a.isNull()); + QVERIFY(!a.isDetached()); const char *zero = nullptr; QVERIFY(!QString::asprintf(zero).isNull()); @@ -1056,6 +1096,8 @@ void tst_QString::isEmpty() { QString a; QVERIFY(a.isEmpty()); + QVERIFY(!a.isDetached()); + QString c("Not empty"); QVERIFY(!c.isEmpty()); } @@ -1157,6 +1199,24 @@ void tst_QString::constructorQByteArray() void tst_QString::STL() { + QString nullStr; + QVERIFY(nullStr.toStdWString().empty()); + QVERIFY(!nullStr.isDetached()); + + wchar_t dataArray[] = { 'w', 'o', 'r', 'l', 'd', 0 }; + + QCOMPARE(nullStr.toWCharArray(dataArray), 0); + QVERIFY(dataArray[0] == 'w'); // array was not modified + QVERIFY(!nullStr.isDetached()); + + QString emptyStr(""); + QVERIFY(emptyStr.toStdWString().empty()); + QVERIFY(!emptyStr.isDetached()); + + QCOMPARE(emptyStr.toWCharArray(dataArray), 0); + QVERIFY(dataArray[0] == 'w'); // array was not modified + QVERIFY(!emptyStr.isDetached()); + std::string stdstr( "QString" ); QString stlqt = QString::fromStdString(stdstr); @@ -1170,6 +1230,11 @@ void tst_QString::STL() QCOMPARE(s, QString::fromLatin1("hello")); QCOMPARE(stlStr, s.toStdWString()); + + // replacing the content of dataArray by calling toWCharArray() + QCOMPARE(s.toWCharArray(dataArray), 5); + const std::wstring stlStrFromUpdatedArray = dataArray; + QCOMPARE(stlStrFromUpdatedArray, stlStr); } void tst_QString::macTypes() @@ -1184,6 +1249,24 @@ void tst_QString::macTypes() void tst_QString::truncate() { + QString nullStr; + nullStr.truncate(5); + QVERIFY(nullStr.isEmpty()); + nullStr.truncate(0); + QVERIFY(nullStr.isEmpty()); + nullStr.truncate(-3); + QVERIFY(nullStr.isEmpty()); + QVERIFY(!nullStr.isDetached()); + + QString emptyStr(""); + emptyStr.truncate(5); + QVERIFY(emptyStr.isEmpty()); + emptyStr.truncate(0); + QVERIFY(emptyStr.isEmpty()); + emptyStr.truncate(-3); + QVERIFY(emptyStr.isEmpty()); + QVERIFY(!emptyStr.isDetached()); + QString e("String E"); e.truncate(4); QCOMPARE(e, QLatin1String("Stri")); @@ -1204,6 +1287,10 @@ void tst_QString::chop_data() const QString original("abcd"); + QTest::newRow("null chop 1") << QString() << 1 << QString(); + QTest::newRow("null chop -1") << QString() << -1 << QString(); + QTest::newRow("empty chop 1") << QString("") << 1 << QString(""); + QTest::newRow("empty chop -1") << QString("") << -1 << QString(""); QTest::newRow("data0") << original << 1 << QString("abc"); QTest::newRow("data1") << original << 0 << original; QTest::newRow("data2") << original << -1 << original; @@ -1231,6 +1318,8 @@ void tst_QString::fill() QCOMPARE(f, QLatin1String("fff")); f.fill('F'); QCOMPARE(f, QLatin1String("FFF")); + f.fill('a', 2); + QCOMPARE(f, QLatin1String("aa")); } static inline const void *ptrValue(quintptr v) @@ -1409,12 +1498,13 @@ void tst_QString::indexOf_data() QTest::newRow( "data55" ) << QString("AbC") << QString("BC") << 0 << false << 1; QTest::newRow( "data56" ) << QString("AbC") << QString("BC") << 1 << false << 1; QTest::newRow( "data57" ) << QString("AbC") << QString("BC") << 2 << false << -1; -#if 0 + QTest::newRow( "null-in-null") << QString() << QString() << 0 << false << 0; QTest::newRow( "empty-in-null") << QString() << QString("") << 0 << false << 0; QTest::newRow( "null-in-empty") << QString("") << QString() << 0 << false << 0; QTest::newRow( "empty-in-empty") << QString("") << QString("") << 0 << false << 0; -#endif + QTest::newRow( "data-in-null") << QString() << QString("a") << 0 << false << -1; + QTest::newRow( "data-in-empty") << QString("") << QString("a") << 0 << false << -1; QString s1 = "abc"; @@ -1641,6 +1731,13 @@ void tst_QString::lastIndexOf_data() QTest::newRow("27") << a << "" << int(a.size()) << int(a.size()) << false; QTest::newRow("28") << a << "" << int(a.size()) + 10 << -1 << false; + + QTest::newRow("null-in-null") << QString() << QString() << 0 << 0 << false; + QTest::newRow("empty-in-null") << QString() << QString("") << 0 << 0 << false; + QTest::newRow("null-in-empty") << QString("") << QString() << 0 << 0 << false; + QTest::newRow("empty-in-empty") << QString("") << QString("") << 0 << 0 << false; + QTest::newRow("data-in-null") << QString() << QString("a") << 0 << -1 << false; + QTest::newRow("data-in-empty") << QString("") << QString("a") << 0 << -1 << false; } void tst_QString::lastIndexOf() @@ -1738,6 +1835,30 @@ void tst_QString::count() QCOMPARE(a.count(view),2); QCOMPARE(a.count(view,Qt::CaseInsensitive),3); QCOMPARE(a.count( QStringView(), Qt::CaseInsensitive), 16); + + QString nullStr; + QCOMPARE(nullStr.count(), 0); + QCOMPARE(nullStr.count('A'), 0); + QCOMPARE(nullStr.count("AB"), 0); + QCOMPARE(nullStr.count(view), 0); + QCOMPARE(nullStr.count(QString()), 1); + QCOMPARE(nullStr.count(""), 1); + QCOMPARE(nullStr.count(QRegularExpression("")), 1); + QCOMPARE(nullStr.count(QRegularExpression("[FG][HI]")), 0); + QTest::ignoreMessage(QtWarningMsg, "QString::count: invalid QRegularExpression object"); + QCOMPARE(nullStr.count(QRegularExpression("invalid regex\\")), 0); + + QString emptyStr(""); + QCOMPARE(emptyStr.count(), 0); + QCOMPARE(emptyStr.count('A'), 0); + QCOMPARE(emptyStr.count("AB"), 0); + QCOMPARE(emptyStr.count(view), 0); + QCOMPARE(emptyStr.count(QString()), 1); + QCOMPARE(emptyStr.count(""), 1); + QCOMPARE(emptyStr.count(QRegularExpression("")), 1); + QCOMPARE(emptyStr.count(QRegularExpression("[FG][HI]")), 0); + QTest::ignoreMessage(QtWarningMsg, "QString::count: invalid QRegularExpression object"); + QCOMPARE(emptyStr.count(QRegularExpression("invalid regex\\")), 0); } void tst_QString::contains() @@ -1814,12 +1935,44 @@ void tst_QString::contains() QTest::ignoreMessage(QtWarningMsg, "QString::contains: invalid QRegularExpression object"); QVERIFY(!a.contains(QRegularExpression("invalid regex\\"))); + + QString nullStr; + QVERIFY(!nullStr.contains('A')); + QVERIFY(!nullStr.contains("AB")); + QVERIFY(!nullStr.contains(view)); + QVERIFY(!nullStr.contains(QRegularExpression("[FG][HI]"))); + QRegularExpressionMatch nullMatch; + QVERIFY(nullStr.contains(QRegularExpression(""), &nullMatch)); + QVERIFY(nullMatch.hasMatch()); + QCOMPARE(nullMatch.captured(), ""); + QCOMPARE(nullMatch.capturedStart(), 0); + QCOMPARE(nullMatch.capturedEnd(), 0); + QVERIFY(!nullStr.isDetached()); + + QString emptyStr(""); + QVERIFY(!emptyStr.contains('A')); + QVERIFY(!emptyStr.contains("AB")); + QVERIFY(!emptyStr.contains(view)); + QVERIFY(!emptyStr.contains(QRegularExpression("[FG][HI]"))); + QRegularExpressionMatch emptyMatch; + QVERIFY(emptyStr.contains(QRegularExpression(""), &emptyMatch)); + QVERIFY(emptyMatch.hasMatch()); + QCOMPARE(emptyMatch.captured(), ""); + QCOMPARE(emptyMatch.capturedStart(), 0); + QCOMPARE(emptyMatch.capturedEnd(), 0); + QVERIFY(!emptyStr.isDetached()); } void tst_QString::left() { QString a; + + QVERIFY(a.left(0).isNull()); + QVERIFY(a.left(5).isNull()); + QVERIFY(a.left(-4).isNull()); + QVERIFY(!a.isDetached()); + a="ABCDEFGHIEfGEFG"; // 15 chars QCOMPARE(a.left(3), QLatin1String("ABC")); QVERIFY(!a.left(0).isNull()); @@ -1838,6 +1991,12 @@ void tst_QString::left() void tst_QString::right() { QString a; + + QVERIFY(a.right(0).isNull()); + QVERIFY(a.right(5).isNull()); + QVERIFY(a.right(-4).isNull()); + QVERIFY(!a.isDetached()); + a="ABCDEFGHIEfGEFG"; // 15 chars QCOMPARE(a.right(3), QLatin1String("EFG")); QCOMPARE(a.right(0), QLatin1String("")); @@ -1854,6 +2013,13 @@ void tst_QString::right() void tst_QString::mid() { QString a; + + QVERIFY(a.mid(0).isNull()); + QVERIFY(a.mid(5, 6).isNull()); + QVERIFY(a.mid(-4, 3).isNull()); + QVERIFY(a.mid(4, -3).isNull()); + QVERIFY(!a.isDetached()); + a="ABCDEFGHIEfGEFG"; // 15 chars QCOMPARE(a.mid(3,3), QLatin1String("DEF")); @@ -1933,6 +2099,11 @@ void tst_QString::mid() void tst_QString::leftJustified() { QString a; + + QCOMPARE(a.leftJustified(3, '-'), QLatin1String("---")); + QCOMPARE(a.leftJustified(2), QLatin1String(" ")); + QVERIFY(!a.isDetached()); + a="ABC"; QCOMPARE(a.leftJustified(5,'-'), QLatin1String("ABC--")); QCOMPARE(a.leftJustified(4,'-'), QLatin1String("ABC-")); @@ -1942,8 +2113,6 @@ void tst_QString::leftJustified() QCOMPARE(a.leftJustified(1), QLatin1String("ABC")); QCOMPARE(a.leftJustified(0), QLatin1String("ABC")); - QString n; - QVERIFY(!n.leftJustified(3).isNull()); QCOMPARE(a.leftJustified(4,' ',true), QLatin1String("ABC ")); QCOMPARE(a.leftJustified(3,' ',true), QLatin1String("ABC")); QCOMPARE(a.leftJustified(2,' ',true), QLatin1String("AB")); @@ -1954,6 +2123,11 @@ void tst_QString::leftJustified() void tst_QString::rightJustified() { QString a; + + QCOMPARE(a.rightJustified(3, '-'), QLatin1String("---")); + QCOMPARE(a.rightJustified(2), QLatin1String(" ")); + QVERIFY(!a.isDetached()); + a="ABC"; QCOMPARE(a.rightJustified(5,'-'), QLatin1String("--ABC")); QCOMPARE(a.rightJustified(4,'-'), QLatin1String("-ABC")); @@ -1963,8 +2137,6 @@ void tst_QString::rightJustified() QCOMPARE(a.rightJustified(1), QLatin1String("ABC")); QCOMPARE(a.rightJustified(0), QLatin1String("ABC")); - QString n; - QVERIFY(!n.rightJustified(3).isNull()); QCOMPARE(a.rightJustified(4,'-',true), QLatin1String("-ABC")); QCOMPARE(a.rightJustified(4,' ',true), QLatin1String(" ABC")); QCOMPARE(a.rightJustified(3,' ',true), QLatin1String("ABC")); @@ -2002,7 +2174,9 @@ void tst_QString::unicodeTableAccess() void tst_QString::toUpper() { - QCOMPARE( QString().toUpper(), QString() ); + const QString s; + QCOMPARE( s.toUpper(), QString() ); // lvalue + QCOMPARE( QString().toUpper(), QString() ); // rvalue QCOMPARE( QString("").toUpper(), QString("") ); QCOMPARE( QStringLiteral("text").toUpper(), QString("TEXT") ); QCOMPARE( QString("text").toUpper(), QString("TEXT") ); @@ -2072,7 +2246,9 @@ void tst_QString::toUpper() void tst_QString::toLower() { - QCOMPARE( QString().toLower(), QString() ); + const QString s; + QCOMPARE(s.toLower(), QString()); // lvalue + QCOMPARE( QString().toLower(), QString() ); // rvalue QCOMPARE( QString("").toLower(), QString("") ); QCOMPARE( QString("text").toLower(), QString("text") ); QCOMPARE( QStringLiteral("Text").toLower(), QString("text") ); @@ -2205,7 +2381,9 @@ void tst_QString::isLower_isUpper() void tst_QString::toCaseFolded() { - QCOMPARE( QString().toCaseFolded(), QString() ); + const QString s; + QCOMPARE( s.toCaseFolded(), QString() ); // lvalue + QCOMPARE( QString().toCaseFolded(), QString() ); // rvalue QCOMPARE( QString("").toCaseFolded(), QString("") ); QCOMPARE( QString("text").toCaseFolded(), QString("text") ); QCOMPARE( QString("Text").toCaseFolded(), QString("text") ); @@ -2261,6 +2439,11 @@ void tst_QString::toCaseFolded() void tst_QString::trimmed() { QString a; + + QVERIFY(a.trimmed().isNull()); // lvalue + QVERIFY(QString().trimmed().isNull()); // rvalue + QVERIFY(!a.isDetached()); + a="Text"; QCOMPARE(a, QLatin1String("Text")); QCOMPARE(a.trimmed(), QLatin1String("Text")); @@ -3569,6 +3752,11 @@ void tst_QString::toUInt() { bool ok; QString a; + + QCOMPARE(a.toUInt(), 0u); + QCOMPARE(a.toUInt(&ok), 0u); + QVERIFY(!ok); + a="3234567890"; QCOMPARE(a.toUInt(&ok),3234567890u); QVERIFY(ok); @@ -3658,6 +3846,11 @@ void tst_QString::toULongLong() { QString str; bool ok; + + QCOMPARE(str.toULongLong(), Q_UINT64_C(0)); + QCOMPARE(str.toULongLong(&ok), Q_UINT64_C(0)); + QVERIFY(!ok); + str = "18446744073709551615"; // ULLONG_MAX QCOMPARE( str.toULongLong( 0 ), Q_UINT64_C(18446744073709551615) ); QCOMPARE( str.toULongLong( &ok ), Q_UINT64_C(18446744073709551615) ); @@ -3679,6 +3872,10 @@ void tst_QString::toLongLong() QString str; bool ok; + QCOMPARE(str.toLongLong(0), Q_INT64_C(0)); + QCOMPARE(str.toLongLong(&ok), Q_INT64_C(0)); + QVERIFY(!ok); + str = "9223372036854775807"; // LLONG_MAX QCOMPARE( str.toLongLong( 0 ), Q_INT64_C(9223372036854775807) ); QCOMPARE( str.toLongLong( &ok ), Q_INT64_C(9223372036854775807) ); @@ -3728,6 +3925,11 @@ void tst_QString::toFloat() { QString a; bool ok; + + QCOMPARE(a.toFloat(), 0.0f); + QCOMPARE(a.toFloat(&ok), 0.0f); + QVERIFY(!ok); + a="0.000000000931322574615478515625"; QCOMPARE(a.toFloat(&ok),(float)(0.000000000931322574615478515625)); QVERIFY(ok); @@ -3739,6 +3941,9 @@ void tst_QString::toDouble_data() QTest::addColumn("result" ); QTest::addColumn("result_ok" ); + QTest::newRow("null") << QString() << 0.0 << false; + QTest::newRow("empty") << QString("") << 0.0 << false; + QTest::newRow( "ok00" ) << QString("0.000000000931322574615478515625") << 0.000000000931322574615478515625 << true; QTest::newRow( "ok01" ) << QString(" 123.45") << 123.45 << true; @@ -3821,6 +4026,15 @@ void tst_QString::setNum() void tst_QString::startsWith() { QString a; + + QVERIFY(!a.startsWith('A')); + QVERIFY(!a.startsWith("AB")); + { + CREATE_VIEW("AB"); + QVERIFY(!a.startsWith(view)); + } + QVERIFY(!a.isDetached()); + a = "AB"; QVERIFY( a.startsWith("A") ); QVERIFY( a.startsWith("AB") ); @@ -3928,6 +4142,15 @@ void tst_QString::startsWith() void tst_QString::endsWith() { QString a; + + QVERIFY(!a.endsWith('A')); + QVERIFY(!a.endsWith("AB")); + { + CREATE_VIEW("AB"); + QVERIFY(!a.endsWith(view)); + } + QVERIFY(!a.isDetached()); + a = "AB"; QVERIFY( a.endsWith("B") ); QVERIFY( a.endsWith("AB") ); @@ -4144,19 +4367,48 @@ void tst_QString::setRawData() QVERIFY(cstr.data_ptr() != csd); } +void tst_QString::setUnicode() +{ + const QChar ptr[] = { QChar(0x1234), QChar(0x0000) }; + + QString str; + QVERIFY(!str.isDetached()); + str.setUnicode(ptr, 1); + // make sure that the data is copied + QVERIFY(str.constData() != ptr); + QVERIFY(str.isDetached()); + QCOMPARE(str, QString(ptr, 1)); + + // make sure that the string is resized, even if the data is nullptr + str = "test"; + QCOMPARE(str.size(), 4); + str.setUnicode(nullptr, 1); + QCOMPARE(str.size(), 1); + QCOMPARE(str, u"t"); +} + void tst_QString::fromStdString() { + QVERIFY(QString::fromStdString(std::string()).isEmpty()); std::string stroustrup = "foo"; QString eng = QString::fromStdString( stroustrup ); QCOMPARE( eng, QString("foo") ); const char cnull[] = "Embedded\0null\0character!"; std::string stdnull( cnull, sizeof(cnull)-1 ); QString qtnull = QString::fromStdString( stdnull ); - QCOMPARE( qtnull.size(), int(stdnull.size()) ); + QCOMPARE(qtnull.size(), qsizetype(stdnull.size())); } void tst_QString::toStdString() { + QString nullStr; + QVERIFY(nullStr.toStdString().empty()); + QVERIFY(!nullStr.isDetached()); + + QString emptyStr(""); + QVERIFY(emptyStr.toStdString().empty()); + QVERIFY(!emptyStr.isDetached()); + QString nord = "foo"; std::string stroustrup1 = nord.toStdString(); QVERIFY( qstrcmp(stroustrup1.c_str(), "foo") == 0 ); @@ -4178,6 +4430,9 @@ void tst_QString::utf8() QFETCH( QString, res ); QCOMPARE(res.toUtf8(), utf8); + + // try rvalue version + QCOMPARE(std::move(res).toUtf8(), utf8); } void tst_QString::fromUtf8_data() @@ -4644,6 +4899,7 @@ void tst_QString::toUcs4() QString s; QList ucs4; QCOMPARE( s.toUcs4().size(), 0 ); + QVERIFY(!s.isDetached()); static const QChar bmp = QLatin1Char('a'); s = QString(&bmp, 1); @@ -4725,6 +4981,7 @@ void tst_QString::arg() TransientDefaultLocale transient(QLocale(QString("de_DE"))); + QString s3; QString s4( "[%0]" ); QString s5( "[%1]" ); QString s6( "[%3]" ); @@ -4785,6 +5042,8 @@ void tst_QString::arg() QCOMPARE( s4.arg(Q_INT64_C(9223372036854775807)), // LLONG_MAX QLatin1String("[9223372036854775807]") ); + QTest::ignoreMessage(QtWarningMsg, "QString::arg: Argument missing: , foo"); + QCOMPARE(QString().arg("foo"), QString()); QTest::ignoreMessage(QtWarningMsg, "QString::arg: Argument missing: \"\" , 0"); QCOMPARE( QString().arg(0), QString() ); QTest::ignoreMessage(QtWarningMsg, "QString::arg: Argument missing: \"\" , 0"); @@ -4985,30 +5244,30 @@ void tst_QString::capacity_data() void tst_QString::capacity() { QFETCH( QString, s1 ); - QFETCH( int, res ); + QFETCH( qsizetype, res ); QString s2( s1 ); s2.reserve( res ); - QVERIFY( (int)s2.capacity() >= res ); + QVERIFY( s2.capacity() >= res ); QCOMPARE( s2, s1 ); s2 = s1; // share again s2.reserve( res * 2 ); - QVERIFY( (int)s2.capacity() >= res * 2 ); + QVERIFY( s2.capacity() >= res * 2 ); if (res != 0) // can both point to QString::_empty when empty QVERIFY(s2.constData() != s1.constData()); QCOMPARE( s2, s1 ); // don't share again -- s2 must be detached for squeeze() to do anything s2.squeeze(); - QVERIFY( (int)s2.capacity() == res ); + QVERIFY( s2.capacity() == res ); QCOMPARE( s2, s1 ); s2 = s1; // share again int oldsize = s1.size(); s2.reserve( res / 2 ); - QVERIFY( (int)s2.capacity() >= res / 2 ); - QVERIFY( (int)s2.capacity() >= oldsize ); + QVERIFY( s2.capacity() >= res / 2 ); + QVERIFY( s2.capacity() >= oldsize ); QCOMPARE( s2, s1 ); } @@ -5022,6 +5281,8 @@ void tst_QString::section_data() QTest::addColumn("sectionString" ); QTest::addColumn("regexp" ); + QTest::newRow("null") << QString() << QString(",") << 0 << -1 << int(QString::SectionDefault) << QString() << false; + QTest::newRow("empty") << QString("") << QString(",") << 0 << -1 << int(QString::SectionDefault) << QString("") << false; QTest::newRow( "data0" ) << QString("forename,middlename,surname,phone") << QString(",") << 2 << 2 << int(QString::SectionDefault) << QString("surname") << false; QTest::newRow( "data1" ) << QString("/usr/local/bin/myapp") << QString("/") << 3 << 4 << int(QString::SectionDefault) << QString("bin/myapp") << false; QTest::newRow( "data2" ) << QString("/usr/local/bin/myapp") << QString("/") << 3 << 3 << int(QString::SectionSkipEmpty) << QString("myapp") << false; @@ -5699,6 +5960,13 @@ void tst_QString::localeAwareCompare_data() QTest::newRow("en@4.lt.6") << QByteArray("en_US") << QString("4") << QString("6") << -1; QTest::newRow("en@5.l6.6") << QByteArray("en_US") << QString("5") << QString("6") << -1; + QTest::newRow("en@null.eq.null") << QByteArray("en_US") << QString() << QString() << 0; + QTest::newRow("en@empty.eq.null") << QByteArray("en_US") << QString("") << QString() << 0; + QTest::newRow("en@null.lt.non-empty") << QByteArray("en_US") << QString() + << QString("test") << -1; + QTest::newRow("en@empty.lt.non-empty") << QByteArray("en_US") << QString("") + << QString("test") << -1; + countGroups++; } @@ -5820,8 +6088,55 @@ void tst_QString::localeAwareCompare() QCOMPARE(sign(QString::localeAwareCompare(s2, s1)), -result); } +void tst_QString::iterators() +{ + QString emptyStr; + QCOMPARE(emptyStr.constBegin(), emptyStr.constEnd()); + QCOMPARE(emptyStr.cbegin(), emptyStr.cend()); + QVERIFY(!emptyStr.isDetached()); + QCOMPARE(emptyStr.begin(), emptyStr.end()); + + QString s = "0123456789"; + + auto it = s.begin(); + auto constIt = s.cbegin(); + qsizetype idx = 0; + + QCOMPARE(*it, s[idx]); + QCOMPARE(*constIt, s[idx]); + + it++; + constIt++; + idx++; + QCOMPARE(*it, s[idx]); + QCOMPARE(*constIt, s[idx]); + + it += 5; + constIt += 5; + idx += 5; + QCOMPARE(*it, s[idx]); + QCOMPARE(*constIt, s[idx]); + + it -= 3; + constIt -= 3; + idx -= 3; + QCOMPARE(*it, s[idx]); + QCOMPARE(*constIt, s[idx]); + + it--; + constIt--; + idx--; + QCOMPARE(*it, s[idx]); + QCOMPARE(*constIt, s[idx]); +} + void tst_QString::reverseIterators() { + QString emptyStr; + QCOMPARE(emptyStr.crbegin(), emptyStr.crend()); + QVERIFY(!emptyStr.isDetached()); + QCOMPARE(emptyStr.rbegin(), emptyStr.rend()); + QString s = "1234"; QString sr = s; std::reverse(sr.begin(), sr.end()); @@ -5851,6 +6166,7 @@ void tst_QString::split_data() QTest::newRow("all-empty") << "" << "" << (QStringList() << "" << ""); QTest::newRow("sep-empty") << "abc" << "" << (QStringList() << "" << "a" << "b" << "c" << ""); + QTest::newRow("null-empty") << QString() << " " << QStringList { "" }; } template struct StringSplitWrapper; @@ -6006,6 +6322,16 @@ void tst_QString::fromUtf16_char16() void tst_QString::unicodeStrings() { + QString nullStr; + QVERIFY(nullStr.toStdU16String().empty()); + QVERIFY(nullStr.toStdU32String().empty()); + QVERIFY(!nullStr.isDetached()); + + QString emptyStr(""); + QVERIFY(emptyStr.toStdU16String().empty()); + QVERIFY(emptyStr.toStdU32String().empty()); + QVERIFY(!emptyStr.isDetached()); + QString s1, s2; static const std::u16string u16str1(u"Hello Unicode World"); static const std::u32string u32str1(U"Hello Unicode World"); @@ -6348,7 +6674,12 @@ void tst_QString::compare() void tst_QString::resize() { - QString s = QLatin1String("hello world"); + QString s; + s.resize(11, ' '); + QCOMPARE(s.size(), 11); + QCOMPARE(s, QLatin1String(" ")); + + s = QLatin1String("hello world"); s.resize(5); QCOMPARE(s, QLatin1String("hello")); @@ -6782,6 +7113,8 @@ void tst_QString::reserve() nil2.squeeze(); nil1.squeeze(); nil2.reserve(0); + QVERIFY(!nil1.isDetached()); + QVERIFY(!nil2.isDetached()); } void tst_QString::toHtmlEscaped_data() @@ -6789,6 +7122,8 @@ void tst_QString::toHtmlEscaped_data() QTest::addColumn("original"); QTest::addColumn("expected"); + QTest::newRow("null") << QString() << QString(); + QTest::newRow("empty") << QString("") << QString(""); QTest::newRow("1") << "Hello World\n" << "Hello World\n"; QTest::newRow("2") << "#include " << "#include <QtCore>"; QTest::newRow("3") << "

plop -->

" @@ -7118,6 +7453,92 @@ void tst_QString::vasprintfWithPrecision() } } +void tst_QString::rawData() +{ + QString s; + // it can be nullptr or a pointer to static shared data + const QChar *constPtr = s.constData(); + QCOMPARE(s.unicode(), constPtr); // unicode() is the same as constData() + QCOMPARE(s.data(), constPtr); // does not detach() on empty string + QCOMPARE(s.utf16(), reinterpret_cast(constPtr)); + QVERIFY(!s.isDetached()); + + s = "abc"; // detached + const QChar *dataConstPtr = s.constData(); + QVERIFY(dataConstPtr != constPtr); + + const ushort *utf16Ptr = s.utf16(); + + QString s1 = s; + QCOMPARE(s1.constData(), dataConstPtr); + QCOMPARE(s1.unicode(), s.unicode()); + + QChar *s1Ptr = s1.data(); // detaches here, because the string is not empty + QVERIFY(s1Ptr != dataConstPtr); + QVERIFY(s1.unicode() != s.unicode()); + + *s1Ptr = 'd'; + QCOMPARE(s1, "dbc"); + + // utf pointer is valid while the string is not changed + QCOMPARE(QString::fromUtf16(utf16Ptr), s); +} + +void tst_QString::clear() +{ + QString s; + s.clear(); + QVERIFY(s.isEmpty()); + QVERIFY(!s.isDetached()); + + s = "some tests string"; + QVERIFY(!s.isEmpty()); + + s.clear(); + QVERIFY(s.isEmpty()); +} + +void tst_QString::sliced() +{ + QString a; + + QVERIFY(a.sliced(0).isEmpty()); + QVERIFY(a.sliced(0, 0).isEmpty()); + QVERIFY(!a.isDetached()); + + a = "ABCDEFGHIEfGEFG"; // 15 chars + + QCOMPARE(a.sliced(5), u"FGHIEfGEFG"); + QCOMPARE(a.sliced(5, 3), u"FGH"); +} + +void tst_QString::chopped() +{ + QString a; + + QVERIFY(a.chopped(0).isEmpty()); + QVERIFY(!a.isDetached()); + + a = "ABCDEFGHIEfGEFG"; // 15 chars + + QCOMPARE(a.chopped(10), u"ABCDE"); +} + +void tst_QString::removeIf() +{ + QString a; + + auto pred = [](const QChar &c) { return c.isLower(); }; + + a.removeIf(pred); + QVERIFY(a.isEmpty()); + QVERIFY(!a.isDetached()); + + a = "aABbcCDd"; + a.removeIf(pred); + QCOMPARE(a, u"ABCD"); +} + // QString's collation order is only supported during the lifetime as QCoreApplication QTEST_GUILESS_MAIN(tst_QString) -- cgit v1.2.3