From c9d597f5db5a88fa3b9f7f9f56e6a0013a9ed903 Mon Sep 17 00:00:00 2001 From: Matthias Rauter Date: Mon, 5 May 2025 15:15:47 +0200 Subject: [PATCH] Extend tests for QUtf8StringView The existing tests were taken from tst_QLatin1StringView. This patch adds the simple tests from tst_QStringView. The tests fromLiteral(), fromRange() and fromContainer() are not included in this patch. Pick-to: 6.9 6.8 6.5 Task-number: QTBUG-132097 Change-Id: I1efc0c2d2f474f6644261575a745aa8f7e5ac4b2 Reviewed-by: Thiago Macieira (cherry picked from commit 26bf2bedca96c2362e7b29f08e9ca978d9496883) Reviewed-by: Qt Cherry-pick Bot --- .../text/qutf8stringview/CMakeLists.txt | 2 + .../qutf8stringview/tst_qutf8stringview.cpp | 236 ++++++++++++++++++ 2 files changed, 238 insertions(+) diff --git a/tests/auto/corelib/text/qutf8stringview/CMakeLists.txt b/tests/auto/corelib/text/qutf8stringview/CMakeLists.txt index 86562fba860..a654e30c123 100644 --- a/tests/auto/corelib/text/qutf8stringview/CMakeLists.txt +++ b/tests/auto/corelib/text/qutf8stringview/CMakeLists.txt @@ -14,6 +14,8 @@ endif() qt_internal_add_test(tst_qutf8stringview SOURCES tst_qutf8stringview.cpp + LIBRARIES + Qt::TestPrivate ) ## Scopes: diff --git a/tests/auto/corelib/text/qutf8stringview/tst_qutf8stringview.cpp b/tests/auto/corelib/text/qutf8stringview/tst_qutf8stringview.cpp index fec6fddd131..03ede935daf 100644 --- a/tests/auto/corelib/text/qutf8stringview/tst_qutf8stringview.cpp +++ b/tests/auto/corelib/text/qutf8stringview/tst_qutf8stringview.cpp @@ -5,6 +5,8 @@ #include #include +#include + #ifdef __cpp_char8_t # define ONLY_IF_CHAR_8_T(expr) expr #else @@ -43,9 +45,16 @@ class tst_QUtf8StringView : public QObject private Q_SLOTS: void fromArraysOfUnknownSize(); void constExpr(); + void basics(); + void literalsChar8(); + void literalsChar(); void construction(); void at(); void arg() const; + void fromQString(); + void comparison(); + void std_stringview_conversion(); + void overloadResolution(); void midLeftRight(); void nullString(); void emptyString(); @@ -126,6 +135,115 @@ void tst_QUtf8StringView::constExpr() } } +void tst_QUtf8StringView::basics() +{ + QUtf8StringView sv1; + + // a default-constructed QStringView is null: + QVERIFY(sv1.isNull()); + // which implies it's empty(); + QVERIFY(sv1.isEmpty()); + + QUtf8StringView sv2; + QT_TEST_ALL_COMPARISON_OPS(sv2, sv1, Qt::strong_ordering::equal); +} + +template +static void testLiteralsWithType(const Char (&hello)[HSize], const Char (&longhello)[LHSize], const Char (&withnull)[WNSize]) +{ + QCOMPARE(QUtf8StringView(hello).size(), 5); + QCOMPARE(QUtf8StringView(hello + 0).size(), 5); // forces decay to pointer + QUtf8StringView sv = hello; + QCOMPARE(sv.size(), 5); + QVERIFY(!sv.empty()); + QVERIFY(!sv.isEmpty()); + QVERIFY(!sv.isNull()); + +#ifdef __cpp_char8_t + QCOMPARE(*sv.utf8(), u8'H'); +#endif + QCOMPARE(sv[0], u8'H'); + QCOMPARE(sv.at(0), u8'H'); + QCOMPARE(sv.front(), u8'H'); + QCOMPARE(sv.first(1), u8'H'); + QCOMPARE(sv[4], u8'o'); + QCOMPARE(sv.at(4), u8'o'); + QCOMPARE(sv.back(), u8'o'); + QCOMPARE(sv.last(1), u8'o'); + + QCOMPARE(*sv.data(), 'H'); + QCOMPARE(sv[0], 'H'); + QCOMPARE(sv.at(0), 'H'); + QCOMPARE(sv.front(), 'H'); + QCOMPARE(sv.first(1), 'H'); + QCOMPARE(sv[4], 'o'); + QCOMPARE(sv.at(4), 'o'); + QCOMPARE(sv.back(), 'o'); + QCOMPARE(sv.last(1), 'o'); + +#ifdef __cpp_char8_t + { + QUtf8StringView sv2(sv.utf8(), sv.utf8() + sv.size()); + QVERIFY(!sv2.isNull()); + QVERIFY(!sv2.empty()); + QCOMPARE(sv2.size(), 5); + QCOMPARE(sv, sv2); + QCOMPARE(sv.data(), sv2.data()); + } +#endif + + QUtf8StringView sv2(sv.data(), sv.data() + sv.size()); + QVERIFY(!sv2.isNull()); + QVERIFY(!sv2.empty()); + QCOMPARE(sv2.size(), 5); + QCOMPARE(sv, sv2); + QCOMPARE(sv.data(), sv2.data()); + + QUtf8StringView sv3(longhello); + QCOMPARE(size_t(sv3.size()), sizeof(longhello)/sizeof(longhello[0]) - 1); + QCOMPARE(sv3.last(1), u'.'); + sv3 = longhello; + QCOMPARE(size_t(sv3.size()), sizeof(longhello)/sizeof(longhello[0]) - 1); + + for (int i = 0; i < sv3.size(); ++i) { + QUtf8StringView sv4(longhello + i); + QCOMPARE(size_t(sv4.size()), sizeof(longhello)/sizeof(longhello[0]) - 1 - i); + QCOMPARE(sv4.last(1), u'.'); + sv4 = longhello + i; + QCOMPARE(size_t(sv4.size()), sizeof(longhello)/sizeof(longhello[0]) - 1 - i); + } + + // these are different results + QCOMPARE(size_t(QUtf8StringView(withnull).size()), size_t(1)); + QCOMPARE(size_t(QUtf8StringView::fromArray(withnull).size()), sizeof(withnull)/sizeof(withnull[0])); + QCOMPARE(QUtf8StringView(withnull + 0).size(), qsizetype(1)); +}; + + +void tst_QUtf8StringView::literalsChar8() +{ +#ifdef __cpp_char8_t + const char8_t hello[] = u8"Hello"; + const char8_t longhello[] = + u8"Hello World. This is a much longer message, to exercise qustrlen."; + const char8_t withnull[] = u8"a\0zzz"; + static_assert(sizeof(longhello) >= 16); + + testLiteralsWithType(hello, longhello, withnull); +#endif +} + +void tst_QUtf8StringView::literalsChar() +{ + const char hello[] = "Hello"; + const char longhello[] = + "Hello World. This is a much longer message, to exercise qustrlen."; + const char withnull[] = "a\0zzz"; + static_assert(sizeof(longhello) >= 16); + + testLiteralsWithType(hello, longhello, withnull); +} + void tst_QUtf8StringView::construction() { { @@ -206,6 +324,11 @@ void tst_QUtf8StringView::at() void tst_QUtf8StringView::arg() const { + // nullness checks + QCOMPARE(QUtf8StringView().arg(QUtf8StringView()), ""); + QCOMPARE(QUtf8StringView("%1").arg(nullptr), ""); + QCOMPARE(QUtf8StringView(u8"%1").arg(nullptr), ""); + #define CHECK1(pattern, arg1, expected) \ do { \ auto p = QUtf8StringView(pattern); \ @@ -249,6 +372,119 @@ void tst_QUtf8StringView::arg() const " \r \r c C "); } +void tst_QUtf8StringView::fromQString() +{ + QString null; + QString empty = ""; + QString normal = "hello"; + + QVERIFY( QUtf8StringView(null.toUtf8()).isNull()); + QVERIFY( QUtf8StringView(null.toUtf8()).isEmpty()); + QVERIFY( QUtf8StringView(empty.toUtf8()).isEmpty()); + QVERIFY(!QUtf8StringView(empty.toUtf8()).isNull()); + QVERIFY(!QUtf8StringView(normal.toUtf8()).isEmpty()); + QVERIFY(!QUtf8StringView(normal.toUtf8()).isNull()); + QCOMPARE(QUtf8StringView(normal.toUtf8()), u"hello"); +} + +void tst_QUtf8StringView::comparison() +{ + const QUtf8StringView aa = u8"aa"; + const QUtf8StringView upperAa = u8"AA"; + const QUtf8StringView bb = u8"bb"; + + QVERIFY(aa == aa); + QVERIFY(aa != bb); + QVERIFY(aa < bb); + QVERIFY(bb > aa); + + QT_TEST_ALL_COMPARISON_OPS(aa, aa, Qt::strong_ordering::equal); + QT_TEST_ALL_COMPARISON_OPS(aa, bb, Qt::strong_ordering::less); + + QCOMPARE(aa.compare(aa), 0); + QVERIFY(aa.compare(upperAa) != 0); + QCOMPARE(aa.compare(upperAa, Qt::CaseInsensitive), 0); + QVERIFY(aa.compare(bb) < 0); + QVERIFY(bb.compare(aa) > 0); +} + +void tst_QUtf8StringView::std_stringview_conversion() +{ + { + QUtf8StringView s; + std::basic_string_view sv(s); + QCOMPARE(sv, std::basic_string_view()); + + s = u8""; + sv = s; + QCOMPARE(s.size(), 0); + QCOMPARE(sv.size(), size_t(0)); + QCOMPARE(sv, std::basic_string_view()); + + s = u8"Hello"; + sv = s; + QCOMPARE(sv, std::basic_string_view("Hello")); + + s = QUtf8StringView::fromArray(u8"Hello\0world"); + sv = s; + QCOMPARE(s.size(), 12); + QCOMPARE(sv.size(), size_t(12)); + QCOMPARE(sv, std::basic_string_view("Hello\0world\0", 12)); + } +} + +namespace QUtf8StringViewOverloadResolution { +// QString and QUtf8StringView overloads are ambiguous +// static void test(QString) { } +// but QStringView and QUtf8StringView work +static void test(QStringView) = delete; +static void test(QUtf8StringView) { } +} +#ifdef __cpp_char8_t +extern const char8_t char8ArrayOfUnknownSize[]; +#endif +extern const char charArrayOfUnknownSize[]; + +void tst_QUtf8StringView::overloadResolution() +{ +#ifdef __cpp_char8_t + { + char8_t char8Array[] = u8"test"; + QUtf8StringViewOverloadResolution::test(char8Array); + char8_t *char8Pointer = char8Array; + QUtf8StringViewOverloadResolution::test(char8Pointer); + QUtf8StringViewOverloadResolution::test(char8ArrayOfUnknownSize); + } + + { + std::u8string string; + QUtf8StringViewOverloadResolution::test(string); + QUtf8StringViewOverloadResolution::test(std::as_const(string)); + QUtf8StringViewOverloadResolution::test(std::move(string)); + } +#endif + + { + char charArray[] = "test"; + QUtf8StringViewOverloadResolution::test(charArray); + char *charPointer = charArray; + QUtf8StringViewOverloadResolution::test(charPointer); + QUtf8StringViewOverloadResolution::test(charArrayOfUnknownSize); + } + + { + std::string string; + QUtf8StringViewOverloadResolution::test(string); + QUtf8StringViewOverloadResolution::test(std::as_const(string)); + QUtf8StringViewOverloadResolution::test(std::move(string)); + } +} + +#ifdef __cpp_char8_t +const char8_t char8ArrayOfUnknownSize[] = u8"abc\0def"; +#endif +const char charArrayOfUnknownSize[] = "abc\0def"; + void tst_QUtf8StringView::midLeftRight() { const QUtf8StringView utf8("Hello World");