summaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorEdward Welbourne <edward.welbourne@qt.io>2021-08-27 14:58:57 +0200
committerEdward Welbourne <edward.welbourne@qt.io>2021-08-30 17:46:00 +0200
commit5644af6f8a800a1516360a42ba4c1a8dc61fc516 (patch)
tree0fb11871c40c7f389f95bc227699fdcda8b7889a /tests
parent522ca997d3baab1b88f454bbeea9f357d3969dff (diff)
Replace FreeBSD's strtou?ll() with std::from_chars()-based strntou?ll()
Remove third-party code in favor of STL. Implement (for now) strtou?ll() as inlines on strntou?ll() calling strlen() for the size parameter. (This is not entirely safe, as a string lacking '\0'-termination but with at least some non-matching text after the numeric portion would formerly be parsed just fine, but would now produce a crash. However, strtou?ll() are internal and callers should be ensuring '\0'-termination.) Task-number: QTBUG-74286 Change-Id: I0c8ca7d4f6110367e93b4c0164854a82c5a545e1 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com> Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io>
Diffstat (limited to 'tests')
-rw-r--r--tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp199
-rw-r--r--tests/auto/corelib/text/qlocale/tst_qlocale.cpp3
-rw-r--r--tests/auto/corelib/text/qstring/tst_qstring.cpp76
3 files changed, 258 insertions, 20 deletions
diff --git a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
index 3b7e0efb00..ff04eca14d 100644
--- a/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
+++ b/tests/auto/corelib/text/qbytearray/tst_qbytearray.cpp
@@ -36,6 +36,7 @@
#include <private/qtools_p.h>
#include "../shared/test_number_shared.h"
+#include <limits>
class tst_QByteArray : public QObject
{
@@ -1674,6 +1675,20 @@ void tst_QByteArray::toULong()
QCOMPARE(b, ok);
}
+static QByteArray decNext(QByteArray &&big)
+{
+ // Increments a decimal digit-string (ignoring sign, so decrements if
+ // negative); only intended for taking a boundary value just out of range,
+ // so big is never a string of only 9s (that'd be one less than a power of
+ // ten, which cannot be a power of two, as odd, or one less than one, as the
+ // power of ten isn't a power of two).
+ int i = big.size() - 1;
+ while (big.at(i) == '9')
+ big[i--] = '0';
+ big[i] += 1;
+ return big;
+}
+
void tst_QByteArray::toLongLong_data()
{
QTest::addColumn<QByteArray>("str");
@@ -1689,10 +1704,14 @@ void tst_QByteArray::toLongLong_data()
<< 7679359922672374856LL << true;
QTest::newRow("in range dec neg") << QByteArray("-7679359922672374856") << 10
<< -7679359922672374856LL << true;
- QTest::newRow("in range hex") << QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448LL
- << true;
- QTest::newRow("in range hex neg") << QByteArray("-6A929129A5421448") << 16
- << -0x6A929129A5421448LL << true;
+ QTest::newRow("in range hex")
+ << QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448LL << true;
+ QTest::newRow("in range hex prefix")
+ << QByteArray("0x6A929129A5421448") << 16 << 0x6A929129A5421448LL << true;
+ QTest::newRow("in range hex neg")
+ << QByteArray("-6A929129A5421448") << 16 << -0x6A929129A5421448LL << true;
+ QTest::newRow("in range hex prefix neg")
+ << QByteArray("-0x6A929129A5421448") << 16 << -0x6A929129A5421448LL << true;
QTest::newRow("Fibonacci's last int64") << QByteArray("7540113804746346429") << 10
<< 7540113804746346429LL << true;
@@ -1700,6 +1719,8 @@ void tst_QByteArray::toLongLong_data()
<< 0xABCFFFFFFF123LL << true;
QTest::newRow("trailing spaces") << QByteArray("9876543210\t\r \n") << 10
<< 9876543210LL << true;
+ QTest::newRow("space after plus") << QByteArray("+ 12") << 10 << 0LL << false;
+ QTest::newRow("space after minus") << QByteArray("- 12") << 10 << 0LL << false;
QTest::newRow("leading junk") << QByteArray("q12345") << 10 << 0LL << false;
QTest::newRow("trailing junk") << QByteArray("abc12345t") << 16 << 0LL << false;
@@ -1716,13 +1737,86 @@ void tst_QByteArray::toLongLong_data()
QTest::newRow("base 3") << QByteArray("12012") << 3 << 140LL << true;
QTest::newRow("neg base 3") << QByteArray("-201") << 3 << -19LL << true;
- QTest::newRow("max dec") << QByteArray("9223372036854775807") << 10 << 9223372036854775807LL
- << true;
- QTest::newRow("mix hex") << QByteArray("-7FFFFFFFFFFFFFFF") << 16 << -0x7FFFFFFFFFFFFFFFLL
- << true;
-
- QTest::newRow("max + 1 dec") << QByteArray("9223372036854775808") << 10 << 0LL << false;
- QTest::newRow("min - 1 hex") << QByteArray("-8000000000000001") << 16 << 0LL << false;
+ // Boundary values, first in every base:
+ using LL = std::numeric_limits<qlonglong>;
+ for (int b = 0; b <= 36; ++b) {
+ if (b == 1) // bases 0 and 2 through 36 are allowed
+ ++b;
+ QTest::addRow("max base %d", b)
+ << QByteArray::number(LL::max(), b ? b : 10) << b << LL::max() << true;
+ QTest::addRow("min base %d", b)
+ << QByteArray::number(LL::min(), b ? b : 10) << b << LL::min() << true;
+ }
+ // Check leading zeros don't hit any buffer-too-big problems:
+ QTest::newRow("many-0 max dec")
+ << (QByteArray(512, '0') + QByteArray::number(LL::max())) << 10 << LL::max() << true;
+
+ // Special bases (and let's include some leading space, too !), first decimal:
+ QTest::newRow("max dec, base 0") << QByteArray::number(LL::max()) << 0 << LL::max() << true;
+ QTest::newRow("max space dec")
+ << ("\t\r\n\f\v " + QByteArray::number(LL::max())) << 10 << LL::max() << true;
+ QTest::newRow("max space dec, base 0")
+ << ("\t\r\n\f\v " + QByteArray::number(LL::max())) << 0 << LL::max() << true;
+ QTest::newRow("min dec, base 0") << QByteArray::number(LL::min()) << 0 << LL::min() << true;
+ QTest::newRow("min space dec")
+ << ("\t\r\n\f\v " + QByteArray::number(LL::min())) << 10 << LL::min() << true;
+ QTest::newRow("min space dec, base 0")
+ << ("\t\r\n\f\v " + QByteArray::number(LL::min())) << 0 << LL::min() << true;
+
+ // Hex with prefix:
+ QTest::newRow("max 0x base 0")
+ << ("0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
+ QTest::newRow("max +0x base 0")
+ << ("+0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
+ QTest::newRow("max space 0x base 0")
+ << ("\t\r\n\f\v 0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
+ QTest::newRow("max space +0x base 0")
+ << ("\t\r\n\f\v +0x" + QByteArray::number(LL::max(), 16)) << 0 << LL::max() << true;
+ QByteArray big = QByteArray::number(LL::min(), 16);
+ big.insert(1, "0x"); // after sign
+ QTest::newRow("min hex prefix") << big << 16 << LL::min() << true;
+ QTest::newRow("min 0x base 0") << big << 0 << LL::min() << true;
+ big.prepend("\t\r\n\f\v ");
+ QTest::newRow("min space hex prefix") << big << 16 << LL::min() << true;
+ QTest::newRow("min space 0x base 0") << big << 0 << LL::min() << true;
+
+ // Octal with prefix:
+ QTest::newRow("max octal base 0")
+ << ('0' + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
+ QTest::newRow("max +octal base 0")
+ << ("+0" + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
+ QTest::newRow("max space octal base 0")
+ << ("\t\r\n\f\v 0" + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
+ QTest::newRow("max space +octal base 0")
+ << ("\t\r\n\f\v +0" + QByteArray::number(LL::max(), 8)) << 0 << LL::max() << true;
+ big = QByteArray::number(LL::min(), 8);
+ big.insert(1, '0'); // after sign
+ QTest::newRow("min octal prefix") << big << 8 << LL::min() << true;
+ QTest::newRow("min octal base 0") << big << 0 << LL::min() << true;
+ big.prepend("\t\r\n\f\v ");
+ QTest::newRow("min space octal prefix") << big << 8 << LL::min() << true;
+ QTest::newRow("min space octal base 0") << big << 0 << LL::min() << true;
+
+ // Values *just* out of range:
+ QTest::newRow("max + 1 dec") << decNext(QByteArray::number(LL::max())) << 10 << 0LL << false;
+ QTest::newRow("max + 1 dec base 0")
+ << decNext(QByteArray::number(LL::max())) << 0 << 0LL << false;
+ QTest::newRow("min - 1 dec") << decNext(QByteArray::number(LL::min())) << 10 << 0LL << false;
+ QTest::newRow("min - 1 dec base 0")
+ << decNext(QByteArray::number(LL::min())) << 0 << 0LL << false;
+ // For hex and octal, we know the last digit of min is 0 and skipping its sign gets max+1:
+ big = QByteArray::number(LL::min(), 8);
+ QTest::newRow("max + 1 oct") << big.sliced(1) << 8 << 0LL << false;
+ big[big.size() - 1] = '1';
+ QTest::newRow("min - 1 oct") << big << 8 << 0LL << false;
+ big.insert(1, '0'); // after minus sign
+ QTest::newRow("min - 1 octal base 0") << big << 0 << 0LL << false;
+ big = QByteArray::number(LL::min(), 16);
+ QTest::newRow("max + 1 hex") << big.sliced(1) << 16 << 0LL << false;
+ big[big.size() - 1] = '1';
+ QTest::newRow("min - 1 hex") << big << 16 << 0LL << false;
+ big.insert(1, "0x"); // after minus sign
+ QTest::newRow("min - 1, 0x base 0") << big << 0 << 0LL << false;
}
void tst_QByteArray::toLongLong()
@@ -1749,14 +1843,81 @@ void tst_QByteArray::toULongLong_data()
QTest::addColumn<qulonglong>("result");
QTest::addColumn<bool>("ok");
- QTest::newRow("null") << QByteArray() << 10 << (qulonglong)0 << false;
- QTest::newRow("empty") << QByteArray("") << 10 << (qulonglong)0 << false;
- QTest::newRow("out of base bound") << QByteArray("c") << 10 << (qulonglong)0 << false;
-
- QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << qulonglong(100) << true;
- QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << qulonglong(100) << true;
- QTest::newRow("leading junk") << QByteArray("x100") << 10 << qulonglong(0) << false;
- QTest::newRow("trailing junk") << QByteArray("100x") << 10 << qulonglong(0) << false;
+ QTest::newRow("null") << QByteArray() << 10 << 0ULL << false;
+ QTest::newRow("empty") << QByteArray("") << 10 << 0ULL << false;
+ QTest::newRow("out of base bound") << QByteArray("c") << 10 << 0ULL << false;
+
+ QTest::newRow("in range dec")
+ << QByteArray("7679359922672374856") << 10 << 7679359922672374856ULL << true;
+ QTest::newRow("in range hex")
+ << QByteArray("6A929129A5421448") << 16 << 0x6A929129A5421448ULL << true;
+ QTest::newRow("in range hex prefix")
+ << QByteArray("0x6A929129A5421448") << 16 << 0x6A929129A5421448ULL << true;
+
+ QTest::newRow("leading spaces") << QByteArray(" \n\r\t100") << 10 << 100ULL << true;
+ QTest::newRow("trailing spaces") << QByteArray("100 \n\r\t") << 10 << 100ULL << true;
+ QTest::newRow("leading plus") << QByteArray("+100") << 10 << 100ULL << true;
+ QTest::newRow("space after plus") << QByteArray("+ 12") << 10 << 0ULL << false;
+ QTest::newRow("leading minus") << QByteArray("-100") << 10 << 0ULL << false;
+ QTest::newRow("leading junk") << QByteArray("x100") << 10 << 0ULL << false;
+ QTest::newRow("trailing junk") << QByteArray("100x") << 10 << 0ULL << false;
+
+ QTest::newRow("dec, base 0") << QByteArray("9876543210") << 0 << 9876543210ULL << true;
+ QTest::newRow("hex, base 0") << QByteArray("0x9876543210") << 0 << 0x9876543210ULL << true;
+ QTest::newRow("oct, base 0") << QByteArray("07654321234567") << 0 << 07654321234567ULL << true;
+ QTest::newRow("base 3") << QByteArray("12012") << 3 << 140ULL << true;
+
+ // Boundary values, first in every base:
+ using ULL = std::numeric_limits<qulonglong>;
+ for (int b = 0; b <= 36; ++b) {
+ if (b == 1) // bases 0 and 2 through 36 are allowed
+ ++b;
+ QTest::addRow("max base %d", b)
+ << QByteArray::number(ULL::max(), b ? b : 10) << b << ULL::max() << true;
+ }
+ // Check leading zeros don't hit any buffer-too-big problems:
+ QTest::newRow("many-0 max dec")
+ << (QByteArray(512, '0') + QByteArray::number(ULL::max())) << 10 << ULL::max() << true;
+
+ // Special bases (and let's include some leading space, too !), first decimal:
+ QTest::newRow("max dec, base 0") << QByteArray::number(ULL::max()) << 0 << ULL::max() << true;
+ QTest::newRow("max space dec")
+ << ("\t\r\n\f\v " + QByteArray::number(ULL::max())) << 10 << ULL::max() << true;
+ QTest::newRow("max space dec, base 0")
+ << ("\t\r\n\f\v " + QByteArray::number(ULL::max())) << 0 << ULL::max() << true;
+
+ // Hex with prefix:
+ QTest::newRow("max 0x base 0")
+ << ("0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
+ QTest::newRow("max +0x base 0")
+ << ("+0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
+ QTest::newRow("max space 0x base 0")
+ << ("\t\r\n\f\v 0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
+ QTest::newRow("max space +0x base 0")
+ << ("\t\r\n\f\v +0x" + QByteArray::number(ULL::max(), 16)) << 0 << ULL::max() << true;
+
+ // Octal with prefix:
+ QTest::newRow("max octal base 0")
+ << ('0' + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
+ QTest::newRow("max +octal base 0")
+ << ("+0" + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
+ QTest::newRow("max space octal base 0")
+ << ("\t\r\n\f\v 0" + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
+ QTest::newRow("max space +octal base 0")
+ << ("\t\r\n\f\v +0" + QByteArray::number(ULL::max(), 8)) << 0 << ULL::max() << true;
+
+ // Values *just* out of range:
+ QTest::newRow("max + 1 dec") << decNext(QByteArray::number(ULL::max())) << 10 << 0ULL << false;
+ QTest::newRow("max + 1 dec base 0")
+ << decNext(QByteArray::number(ULL::max())) << 0 << 0ULL << false;
+ auto big = QByteArray::number(ULL::max(), 8).replace('7', '0');
+ // Number of bits is a power of two, so not a multiple of three; so (only)
+ // first digit of max wasn't 7:
+ big[0] += 1;
+ QTest::newRow("max + 1 oct") << big << 8 << 0ULL << false;
+ // Number of bits is a multiple of four, so every digit of max is 'f'.
+ big = '1' + QByteArray::number(ULL::max(), 16).replace('f', '0');
+ QTest::newRow("max + 1 hex") << big << 16 << 0ULL << false;
}
void tst_QByteArray::toULongLong()
diff --git a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
index 89cb46163a..631ca9ff0a 100644
--- a/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
+++ b/tests/auto/corelib/text/qlocale/tst_qlocale.cpp
@@ -1319,6 +1319,9 @@ void tst_QLocale::long_long_conversion_data()
QTest::newRow("C 12345,67") << QString("C") << "12345,67" << false << (qlonglong) 0;
QTest::newRow("C 123456,7") << QString("C") << "123456,7" << false << (qlonglong) 0;
QTest::newRow("C 1,234,567") << QString("C") << "1,234,567" << true << (qlonglong) 1234567;
+ using LL = std::numeric_limits<qlonglong>;
+ QTest::newRow("C LLONG_MIN") << QString("C") << QString::number(LL::min()) << true << LL::min();
+ QTest::newRow("C LLONG_MAX") << QString("C") << QString::number(LL::max()) << true << LL::max();
QTest::newRow("de_DE 1") << QString("de_DE") << "1" << true << (qlonglong) 1;
QTest::newRow("de_DE 1.") << QString("de_DE") << "1." << false << (qlonglong) 0;
diff --git a/tests/auto/corelib/text/qstring/tst_qstring.cpp b/tests/auto/corelib/text/qstring/tst_qstring.cpp
index c2a7b93c7d..a377834025 100644
--- a/tests/auto/corelib/text/qstring/tst_qstring.cpp
+++ b/tests/auto/corelib/text/qstring/tst_qstring.cpp
@@ -3897,7 +3897,7 @@ void tst_QString::toLong()
void tst_QString::toULongLong()
{
QString str;
- bool ok;
+ bool ok = true;
QCOMPARE(str.toULongLong(), Q_UINT64_C(0));
QCOMPARE(str.toULongLong(&ok), Q_UINT64_C(0));
@@ -3917,6 +3917,15 @@ void tst_QString::toULongLong()
QCOMPARE( str.toULongLong( 0 ), Q_UINT64_C(0) );
QCOMPARE( str.toULongLong( &ok ), Q_UINT64_C(0) );
QVERIFY( !ok );
+
+ // Check limits round-trip in every base:
+ using ULL = std::numeric_limits<qulonglong>;
+ for (int b = 0; b <= 36; ++b) {
+ if (b == 1) // 0 and 2 through 36 are valid bases
+ ++b;
+ QCOMPARE(QString::number(ULL::max(), b ? b : 10).toULongLong(&ok, b), ULL::max());
+ QVERIFY(ok);
+ }
}
void tst_QString::toLongLong()
@@ -3969,6 +3978,71 @@ void tst_QString::toLongLong()
}
}
}
+
+ // Check bounds.
+ // First in every base, with no prefix:
+ using LL = std::numeric_limits<qlonglong>;
+ for (int b = 0; b <= 36; ++b) {
+ if (b == 1) // 0 and 2 through 36 are valid bases
+ ++b;
+ QCOMPARE(QString::number(LL::max(), b ? b : 10).toLongLong(&ok, b), LL::max());
+ QVERIFY(ok);
+ QCOMPARE(QString::number(LL::min(), b ? b : 10).toLongLong(&ok, b), LL::min());
+ QVERIFY(ok);
+ }
+
+ // Then in base 16 or 0 with 0x prefix:
+ auto big = QString::number(LL::min(), 16);
+ big.insert(1, u"0x"); // after the minus sign
+ big.prepend(u"\t\r\n\f\v ");
+ QCOMPARE(big.toLongLong(&ok, 16), LL::min());
+ QVERIFY(ok);
+ QCOMPARE(big.toLongLong(&ok, 0), LL::min());
+ QVERIFY(ok);
+ big = QString::number(LL::max(), 16);
+ big.prepend(u"\t\r\n\f\v 0x");
+ QCOMPARE(big.toLongLong(&ok, 16), LL::max());
+ QVERIFY(ok);
+ QCOMPARE(big.toLongLong(&ok, 0), LL::max());
+ QVERIFY(ok);
+ big.insert(6, u'+');
+ QCOMPARE(big.toLongLong(&ok, 16), LL::max());
+ QVERIFY(ok);
+ QCOMPARE(big.toLongLong(&ok, 0), LL::max());
+ QVERIFY(ok);
+
+ // Next octal:
+ big = QString::number(LL::min(), 8);
+ big.insert(1, u'0'); // after the minus sign
+ big.prepend(u"\t\r\n\f\v ");
+ QCOMPARE(big.toLongLong(&ok, 8), LL::min());
+ QVERIFY(ok);
+ QCOMPARE(big.toLongLong(&ok, 0), LL::min());
+ QVERIFY(ok);
+ big = QString::number(LL::max(), 8);
+ big.prepend(u"\t\r\n\f\v 0");
+ QCOMPARE(big.toLongLong(&ok, 8), LL::max());
+ QVERIFY(ok);
+ QCOMPARE(big.toLongLong(&ok, 0), LL::max());
+ QVERIFY(ok);
+ big.insert(6, u'+');
+ QCOMPARE(big.toLongLong(&ok, 8), LL::max());
+ QVERIFY(ok);
+ QCOMPARE(big.toLongLong(&ok, 0), LL::max());
+ QVERIFY(ok);
+
+ // Finally decimal for base 0:
+ big = QString::number(LL::min(), 10);
+ big.prepend(u"\t\r\n\f\v ");
+ QCOMPARE(big.toLongLong(&ok, 0), LL::min());
+ QVERIFY(ok);
+ big = QString::number(LL::max(), 10);
+ big.prepend(u"\t\r\n\f\v ");
+ QCOMPARE(big.toLongLong(&ok, 0), LL::max());
+ QVERIFY(ok);
+ big.insert(6, u'+');
+ QCOMPARE(big.toLongLong(&ok, 0), LL::max());
+ QVERIFY(ok);
}
////////////////////////////////////////////////////////////////////////////