summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp')
-rw-r--r--tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp730
1 files changed, 730 insertions, 0 deletions
diff --git a/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
new file mode 100644
index 0000000000..702e1840da
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
@@ -0,0 +1,730 @@
+// Copyright (C) 2020 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include <QByteArrayView>
+
+#include <QTest>
+
+// for negative testing (can't convert from)
+#include <deque>
+#include <list>
+#include <QVarLengthArray>
+
+template <typename T>
+constexpr bool CanConvert = std::is_convertible_v<T, QByteArrayView>;
+
+static_assert(!CanConvert<QString>);
+static_assert(!CanConvert<QStringView>);
+static_assert(!CanConvert<const char16_t*>);
+
+static_assert(!CanConvert<char>);
+static_assert(CanConvert<char[1]>);
+static_assert(CanConvert<const char[1]>);
+static_assert(CanConvert<char*>);
+static_assert(CanConvert<const char*>);
+
+static_assert(!CanConvert<uchar>);
+static_assert(!CanConvert<uchar[1]>);
+static_assert(!CanConvert<const uchar[1]>);
+static_assert(CanConvert<uchar*>);
+static_assert(CanConvert<const uchar*>);
+
+static_assert(!CanConvert<signed char>);
+static_assert(!CanConvert<signed char[1]>);
+static_assert(!CanConvert<const signed char[1]>);
+static_assert(CanConvert<signed char*>);
+static_assert(CanConvert<const signed char*>);
+
+static_assert(!CanConvert<std::byte>);
+static_assert(!CanConvert<std::byte[1]>);
+static_assert(!CanConvert<const std::byte[1]>);
+static_assert(CanConvert<std::byte*>);
+static_assert(CanConvert<const std::byte*>);
+
+static_assert(CanConvert< QByteArray >);
+static_assert(CanConvert<const QByteArray >);
+static_assert(CanConvert< QByteArray&>);
+static_assert(CanConvert<const QByteArray&>);
+
+static_assert(CanConvert< std::string >);
+static_assert(CanConvert<const std::string >);
+static_assert(CanConvert< std::string&>);
+static_assert(CanConvert<const std::string&>);
+
+static_assert(CanConvert< std::string_view >);
+static_assert(CanConvert<const std::string_view >);
+static_assert(CanConvert< std::string_view&>);
+static_assert(CanConvert<const std::string_view&>);
+
+static_assert(CanConvert< QVector<char> >);
+static_assert(CanConvert<const QVector<char> >);
+static_assert(CanConvert< QVector<char>&>);
+static_assert(CanConvert<const QVector<char>&>);
+
+static_assert(CanConvert< QVarLengthArray<char> >);
+static_assert(CanConvert<const QVarLengthArray<char> >);
+static_assert(CanConvert< QVarLengthArray<char>&>);
+static_assert(CanConvert<const QVarLengthArray<char>&>);
+
+static_assert(CanConvert< std::vector<char> >);
+static_assert(CanConvert<const std::vector<char> >);
+static_assert(CanConvert< std::vector<char>&>);
+static_assert(CanConvert<const std::vector<char>&>);
+
+static_assert(CanConvert< std::array<char, 1> >);
+static_assert(CanConvert<const std::array<char, 1> >);
+static_assert(CanConvert< std::array<char, 1>&>);
+static_assert(CanConvert<const std::array<char, 1>&>);
+
+static_assert(!CanConvert<std::deque<char>>);
+static_assert(!CanConvert<std::list<char>>);
+
+class tst_QByteArrayView : public QObject
+{
+ Q_OBJECT
+private slots:
+ // Note: much of the shared API is tested in ../qbytearrayapisymmetry/
+ void constExpr() const;
+ void basics() const;
+ void literals() const;
+ void fromArray() const;
+ void literalsWithInternalNulls() const;
+ void at() const;
+
+ void fromQByteArray() const;
+
+ void fromCharStar() const
+ {
+ fromEmptyLiteral<char>();
+ conversionTests("Hello, World!");
+ }
+
+ void fromUCharStar() const
+ {
+ fromEmptyLiteral<uchar>();
+
+ const uchar data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ conversionTests(data);
+ }
+
+ void fromSignedCharStar() const
+ {
+ fromEmptyLiteral<signed char>();
+
+ const signed char data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ conversionTests(data);
+ }
+
+ void fromStdByteArray() const
+ {
+ fromEmptyLiteral<std::byte>();
+
+ const std::byte data[] = {std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'},
+ std::byte{'o'}, std::byte{0}};
+ conversionTests(data);
+ }
+
+ void fromCharRange() const
+ {
+ const char data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!' };
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromUCharRange() const
+ {
+ const uchar data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromSignedCharRange() const
+ {
+ const signed char data[] = { 'H', 'e', 'l', 'l', 'o', ',', ' ', 'W', 'o', 'r', 'l', 'd', '!', 0 };
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromStdByteRange() const
+ {
+ const std::byte data[] = {std::byte{'H'}, std::byte{'e'}, std::byte{'l'}, std::byte{'l'},
+ std::byte{'o'}, std::byte{0}};
+ fromRange(std::begin(data), std::end(data));
+ }
+
+ void fromCharContainers() const
+ {
+ fromContainers<char>();
+ }
+
+ void fromUCharContainers() const
+ {
+ fromContainers<uchar>();
+ }
+
+ void fromSignedCharContainers() const
+ {
+ fromContainers<signed char>();
+ }
+
+ void fromStdByteContainers() const
+ {
+ fromContainers<std::byte>();
+ }
+
+ void comparison() const;
+ void compare() const;
+ void std_stringview_conversion();
+
+private:
+ template <typename Data>
+ void conversionTests(Data arg) const;
+ template <typename Char>
+ void fromEmptyLiteral() const;
+ template <typename Char>
+ void fromRange(const Char *first, const Char *last) const;
+ template <typename Char, typename Container>
+ void fromContainer() const;
+ template <typename Char>
+ void fromContainers() const;
+};
+
+void tst_QByteArrayView::constExpr() const
+{
+ // compile-time checks
+ {
+ constexpr QByteArrayView bv;
+ static_assert(bv.size() == 0);
+ static_assert(bv.isNull());
+ static_assert(bv.empty());
+ static_assert(bv.isEmpty());
+ static_assert(bv.data() == nullptr);
+
+ constexpr std::string_view sv = bv;
+ static_assert(sv.size() == 0);
+ static_assert(sv.data() == nullptr);
+
+ constexpr QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(bv2.isNull());
+ static_assert(bv2.empty());
+ }
+ {
+ constexpr QByteArrayView bv = "";
+ static_assert(bv.size() == 0);
+ static_assert(!bv.isNull());
+ static_assert(bv.empty());
+ static_assert(bv.isEmpty());
+ static_assert(bv.data() != nullptr);
+
+ constexpr std::string_view sv = bv;
+ static_assert(sv.size() == bv.size());
+ static_assert(sv.data() == bv.data());
+
+ constexpr QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(!bv2.isNull());
+ static_assert(bv2.empty());
+ }
+ {
+ static_assert(QByteArrayView("Hello").size() == 5);
+ constexpr QByteArrayView bv = "Hello";
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+
+ static_assert(*bv.begin() == 'H' );
+ static_assert(*(bv.end() - 1) == 'o' );
+ static_assert(*bv.cbegin() == 'H' );
+ static_assert(*(bv.cend() - 1) == 'o' );
+ static_assert(*bv.rbegin() == 'o' );
+ static_assert(*bv.crbegin() == 'o' );
+
+ // This is just to test that rend()/crend() are constexpr.
+ static_assert(bv.rbegin() != bv.rend());
+ static_assert(bv.crbegin() != bv.crend());
+
+ constexpr std::string_view sv = bv;
+ static_assert(sv.size() == bv.size());
+ static_assert(sv.data() == bv.data());
+#ifdef AMBIGUOUS_CALL // QTBUG-108805
+ static_assert(sv == bv);
+ static_assert(bv == sv);
+#endif
+
+ constexpr QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(!bv2.isNull());
+ static_assert(!bv2.empty());
+ static_assert(bv2.size() == 5);
+ }
+#if !defined(Q_CC_GNU_ONLY) || !defined(QT_SANITIZE_UNDEFINED)
+ // Below checks are disabled because of a compilation issue with GCC and
+ // -fsanitize=undefined. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=71962.
+ {
+ static constexpr char hello[] = "Hello";
+ constexpr QByteArrayView bv(hello);
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+
+ constexpr std::string_view sv = bv;
+ static_assert(bv.size() == sv.size());
+#ifdef AMBIGUOUS_CALL // QTBUG-108805
+ static_assert(bv == sv);
+ static_assert(sv == bv);
+#endif
+ }
+ {
+ static constexpr char hello[] = { 'H', 'e', 'l', 'l', 'o' };
+ constexpr QByteArrayView bv(hello, std::size(hello));
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+
+ constexpr auto bv2 = QByteArrayView::fromArray(hello);
+ QCOMPARE_EQ(bv, bv2);
+
+ constexpr std::string_view sv = bv;
+ static_assert(bv.size() == sv.size());
+#ifdef AMBIGUOUS_CALL // QTBUG-108805
+ static_assert(bv == sv);
+ static_assert(sv == bv);
+#endif
+ }
+#endif
+ {
+ constexpr char *null = nullptr;
+ constexpr QByteArrayView bv(null);
+ static_assert(bv.isNull());
+ static_assert(bv.isEmpty());
+ static_assert(bv.size() == 0);
+
+ constexpr std::string_view sv = bv;
+ static_assert(sv.size() == 0);
+ static_assert(sv.data() == nullptr);
+ }
+ {
+ constexpr QByteArrayView bv(QLatin1StringView("Hello"));
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+ }
+ {
+ constexpr QByteArrayView bv(QUtf8StringView("Hello"));
+ static_assert(bv.size() == 5);
+ static_assert(!bv.empty());
+ static_assert(!bv.isEmpty());
+ static_assert(!bv.isNull());
+ static_assert(*bv.data() == 'H');
+ static_assert(bv[0] == 'H');
+ static_assert(bv.at(0) == 'H');
+ static_assert(bv.front() == 'H');
+ static_assert(bv.first() == 'H');
+ static_assert(bv[4] == 'o');
+ static_assert(bv.at(4) == 'o');
+ static_assert(bv.back() == 'o');
+ static_assert(bv.last() == 'o');
+ }
+}
+
+void tst_QByteArrayView::basics() const
+{
+ QByteArrayView bv1;
+
+ // a default-constructed QByteArrayView is null:
+ QVERIFY(bv1.isNull());
+ // which implies it's empty();
+ QVERIFY(bv1.isEmpty());
+
+ QByteArrayView bv2;
+
+ QVERIFY(bv2 == bv1);
+ QVERIFY(!(bv2 != bv1));
+}
+
+// Note: initially the size would be deduced from the array literal,
+// but it caused source compatibility issues so this is currently not the case.
+void tst_QByteArrayView::literals() const
+{
+ const char hello[] = "Hello\0This shouldn't be found";
+
+ QCOMPARE(QByteArrayView(hello).size(), 5);
+ QCOMPARE(QByteArrayView(hello + 0).size(), 5); // forces decay to pointer
+ QByteArrayView bv = hello;
+ QCOMPARE(bv.size(), 5);
+ QVERIFY(!bv.empty());
+ QVERIFY(!bv.isEmpty());
+ QVERIFY(!bv.isNull());
+ QCOMPARE(*bv.data(), 'H');
+ QCOMPARE(bv[0], 'H');
+ QCOMPARE(bv.at(0), 'H');
+ QCOMPARE(bv.front(), 'H');
+ QCOMPARE(bv.first(), 'H');
+ QCOMPARE(bv[4], 'o');
+ QCOMPARE(bv.at(4), 'o');
+ QCOMPARE(bv.back(), 'o');
+ QCOMPARE(bv.last(), 'o');
+
+ QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ QVERIFY(!bv2.isNull());
+ QVERIFY(!bv2.empty());
+ QCOMPARE(bv2.size(), 5);
+
+ const char abc[] = "abc";
+ bv = abc;
+ QCOMPARE(bv.size(), 3);
+
+ const char def[3] = {'d', 'e', 'f'};
+ bv = def;
+ QCOMPARE(bv.size(), 3);
+}
+
+void tst_QByteArrayView::fromArray() const
+{
+ static constexpr char hello[] = "Hello\0abc\0\0.";
+
+ const QByteArrayView bv = QByteArrayView::fromArray(hello);
+ QCOMPARE(bv.size(), 13);
+ QVERIFY(!bv.empty());
+ QVERIFY(!bv.isEmpty());
+ QVERIFY(!bv.isNull());
+ QCOMPARE(*bv.data(), 'H');
+ QCOMPARE(bv[0], 'H');
+ QCOMPARE(bv.at(0), 'H');
+ QCOMPARE(bv.front(), 'H');
+ QCOMPARE(bv.first(), 'H');
+ QCOMPARE(bv[4], 'o');
+ QCOMPARE(bv.at(4), 'o');
+ QCOMPARE(bv[5], '\0');
+ QCOMPARE(bv.at(5), '\0');
+ QCOMPARE(*(bv.data() + bv.size() - 2), '.');
+ QCOMPARE(bv.back(), '\0');
+ QCOMPARE(bv.last(), '\0');
+
+ const std::byte bytes[] = {std::byte(0x0), std::byte(0x1), std::byte(0x2)};
+ QByteArrayView bbv = QByteArrayView::fromArray(bytes);
+ QCOMPARE(bbv.data(), reinterpret_cast<const char *>(bytes + 0));
+ QCOMPARE(bbv.size(), 3);
+ QCOMPARE(bbv.first(), 0x0);
+ QCOMPARE(bbv.last(), 0x2);
+}
+
+void tst_QByteArrayView::literalsWithInternalNulls() const
+{
+ const char withnull[] = "a\0zzz";
+
+ // these are different results
+ QCOMPARE(size_t(QByteArrayView::fromArray(withnull).size()), std::size(withnull));
+ QCOMPARE(QByteArrayView(withnull + 0).size(), 1);
+
+ QByteArrayView nulled = QByteArrayView::fromArray(withnull);
+ QCOMPARE(nulled.last(), '\0');
+ nulled.chop(1); // cut off trailing \0
+ QCOMPARE(nulled[1], '\0');
+ QCOMPARE(nulled.indexOf('\0'), 1);
+ QCOMPARE(nulled.indexOf('z'), 2);
+ QCOMPARE(nulled.lastIndexOf('z'), 4);
+ QCOMPARE(nulled.lastIndexOf('a'), 0);
+ QVERIFY(nulled.startsWith("a\0z"));
+ QVERIFY(nulled.startsWith("a\0y"));
+ QVERIFY(!nulled.startsWith(QByteArrayView("a\0y", 3)));
+ QVERIFY(nulled.endsWith("zz"));
+ QVERIFY(nulled.contains("z"));
+ QVERIFY(nulled.contains(QByteArrayView("\0z", 2)));
+ QVERIFY(!nulled.contains(QByteArrayView("\0y", 2)));
+ QCOMPARE(nulled.first(5), QByteArrayView(withnull, 5));
+ QCOMPARE(nulled.last(5), QByteArrayView(withnull, 5));
+ QCOMPARE(nulled.sliced(0), QByteArrayView(withnull, 5));
+ QCOMPARE(nulled.sliced(2, 2), "zz");
+ QCOMPARE(nulled.chopped(2), QByteArrayView("a\0z", 3));
+ QVERIFY(nulled.chopped(2) != QByteArrayView("a\0y", 3));
+ QCOMPARE(nulled.count('z'), 3);
+
+ const char nullfirst[] = "\0buzz";
+ QByteArrayView fromnull = QByteArrayView::fromArray(nullfirst);
+ QVERIFY(!fromnull.isEmpty());
+
+ const char nullNotEnd[] = { 'b', 'o', 'w', '\0', 'a', 'f', 't', 'z' };
+ QByteArrayView midNull = QByteArrayView::fromArray(nullNotEnd);
+ QCOMPARE(midNull.back(), 'z');
+}
+
+void tst_QByteArrayView::at() const
+{
+ QByteArray hello("Hello");
+ QByteArrayView bv(hello);
+ QCOMPARE(bv.at(0), 'H'); QCOMPARE(bv[0], 'H');
+ QCOMPARE(bv.at(1), 'e'); QCOMPARE(bv[1], 'e');
+ QCOMPARE(bv.at(2), 'l'); QCOMPARE(bv[2], 'l');
+ QCOMPARE(bv.at(3), 'l'); QCOMPARE(bv[3], 'l');
+ QCOMPARE(bv.at(4), 'o'); QCOMPARE(bv[4], 'o');
+}
+
+void tst_QByteArrayView::fromQByteArray() const
+{
+ QByteArray null;
+ QByteArray empty = "";
+
+ QVERIFY(QByteArrayView(null).isNull());
+ QVERIFY(qToByteArrayViewIgnoringNull(null).isNull());
+
+ QVERIFY(QByteArrayView(null).isEmpty());
+ QVERIFY(qToByteArrayViewIgnoringNull(null).isEmpty());
+
+ QVERIFY(QByteArrayView(empty).isEmpty());
+ QVERIFY(qToByteArrayViewIgnoringNull(empty).isEmpty());
+
+ QVERIFY(!QByteArrayView(empty).isNull());
+ QVERIFY(!qToByteArrayViewIgnoringNull(empty).isNull());
+
+ conversionTests(QByteArray("Hello World!"));
+}
+
+namespace help {
+template <typename T>
+size_t size(const T &t) { return size_t(t.size()); }
+template <typename T>
+size_t size(const T *t) { return std::char_traits<T>::length(t); }
+
+template <typename T>
+decltype(auto) cbegin(const T &t) { return t.begin(); }
+template <typename T>
+const T * cbegin(const T *t) { return t; }
+
+template <typename T>
+decltype(auto) cend(const T &t) { return t.end(); }
+template <typename T>
+const T * cend(const T *t) { return t + size(t); }
+
+template <typename T>
+decltype(auto) crbegin(const T &t) { return t.rbegin(); }
+template <typename T>
+std::reverse_iterator<const T*> crbegin(const T *t) { return std::reverse_iterator<const T*>(cend(t)); }
+
+template <typename T>
+decltype(auto) crend(const T &t) { return t.rend(); }
+template <typename T>
+std::reverse_iterator<const T*> crend(const T *t) { return std::reverse_iterator<const T*>(cbegin(t)); }
+
+} // namespace help
+
+template <typename Data>
+void tst_QByteArrayView::conversionTests(Data data) const
+{
+ // copy-construct:
+ {
+ QByteArrayView bv = data;
+
+ QCOMPARE(help::size(bv), help::size(data));
+
+ const auto compare = [](auto v1, auto v2) {
+ if constexpr (std::is_same_v<decltype(v1), std::byte>)
+ return std::to_integer<char>(v1) == v2;
+ else
+ return v1 == v2;
+ };
+ QVERIFY(std::equal(help::cbegin(data), help::cend(data),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(bv.cbegin(), bv.size()), compare));
+ QVERIFY(std::equal(help::cbegin(data), help::cend(data),
+ QT_MAKE_CHECKED_ARRAY_ITERATOR(bv.begin(), bv.size()), compare));
+ QVERIFY(std::equal(help::crbegin(data), help::crend(data), bv.crbegin(), compare));
+ QVERIFY(std::equal(help::crbegin(data), help::crend(data), bv.rbegin(), compare));
+ QCOMPARE(bv, data);
+ }
+
+ QByteArrayView bv;
+
+ // copy-assign:
+ {
+ bv = data;
+
+ QCOMPARE(help::size(bv), help::size(data));
+
+ // check relational operators:
+
+ QCOMPARE(bv, data);
+ QCOMPARE(data, bv);
+
+ QVERIFY(!(bv != data));
+ QVERIFY(!(data != bv));
+
+ QVERIFY(!(bv < data));
+ QVERIFY(bv <= data);
+ QVERIFY(!(bv > data));
+ QVERIFY(bv >= data);
+
+ QVERIFY(!(data < bv));
+ QVERIFY(data <= bv);
+ QVERIFY(!(data > bv));
+ QVERIFY(data >= bv);
+ }
+
+ // copy-construct from rvalue (QByteArrayView never assumes ownership):
+ {
+ QByteArrayView bv2 = std::move(data);
+ QCOMPARE(bv2, bv);
+ QCOMPARE(bv2, data);
+ }
+
+ // copy-assign from rvalue (QByteArrayView never assumes ownership):
+ {
+ QByteArrayView bv2;
+ bv2 = std::move(data);
+ QCOMPARE(bv2, bv);
+ QCOMPARE(bv2, data);
+ }
+}
+
+template <typename Char>
+void tst_QByteArrayView::fromEmptyLiteral() const
+{
+ const Char *null = nullptr;
+ const Char empty[] = { Char{0} };
+
+ QCOMPARE(QByteArrayView(null).size(), 0);
+ QCOMPARE(QByteArrayView(null).data(), nullptr);
+ QCOMPARE(QByteArrayView::fromArray(empty).size(), 1);
+ QCOMPARE(static_cast<const void*>(QByteArrayView::fromArray(empty).data()),
+ static_cast<const void*>(empty));
+
+ QVERIFY(QByteArrayView(null).isNull());
+ QVERIFY(QByteArrayView(null).isEmpty());
+ QVERIFY(!QByteArrayView::fromArray(empty).isEmpty());
+ QVERIFY(!QByteArrayView::fromArray(empty).isNull());
+}
+
+template <typename Char>
+void tst_QByteArrayView::fromRange(const Char *first, const Char *last) const
+{
+ const Char *null = nullptr;
+ QCOMPARE(QByteArrayView(null, null).size(), 0);
+ QCOMPARE(QByteArrayView(null, null).data(), nullptr);
+ QCOMPARE(QByteArrayView(first, first).size(), 0);
+ QCOMPARE(static_cast<const void*>(QByteArrayView(first, first).data()),
+ static_cast<const void*>(first));
+
+ const auto bv = QByteArrayView(first, last);
+ QCOMPARE(bv.size(), last - first);
+ QCOMPARE(static_cast<const void*>(bv.data()),
+ static_cast<const void*>(first));
+
+ QCOMPARE(static_cast<const void*>(bv.last(0).data()),
+ static_cast<const void*>(last));
+ QCOMPARE(static_cast<const void*>(bv.sliced(bv.size()).data()),
+ static_cast<const void*>(last));
+
+ // can't call conversionTests() here, as it requires a single object
+}
+
+template <typename Char, typename Container>
+void tst_QByteArrayView::fromContainer() const
+{
+ const QByteArray s = "Hello World!";
+
+ Container c;
+ // unspecified whether empty containers make null QByteArrayView
+ QVERIFY(QByteArrayView(c).isEmpty());
+
+ QCOMPARE(sizeof(Char), sizeof(char));
+
+ const auto *data = reinterpret_cast<const Char *>(s.data());
+ std::copy(data, data + s.size(), std::back_inserter(c));
+ conversionTests(std::move(c));
+}
+
+template <typename Char>
+void tst_QByteArrayView::fromContainers() const
+{
+ fromContainer<Char, QVector<Char>>();
+ fromContainer<Char, QVarLengthArray<Char>>();
+ fromContainer<Char, std::vector<Char>>();
+ fromContainer<Char, std::basic_string<Char>>();
+}
+
+void tst_QByteArrayView::comparison() const
+{
+ const QByteArrayView aa = "aa";
+ const QByteArrayView bb = "bb";
+
+ QVERIFY(aa == aa);
+ QVERIFY(aa != bb);
+ QVERIFY(aa < bb);
+ QVERIFY(bb > aa);
+}
+
+void tst_QByteArrayView::compare() const
+{
+ QByteArrayView alpha = "original";
+
+ QVERIFY(alpha.compare("original", Qt::CaseSensitive) == 0);
+ QVERIFY(alpha.compare("Original", Qt::CaseSensitive) > 0);
+ QVERIFY(alpha.compare("Original", Qt::CaseInsensitive) == 0);
+ QByteArrayView beta = "unoriginal";
+ QVERIFY(alpha.compare(beta, Qt::CaseInsensitive) < 0);
+ beta = "Unoriginal";
+ QVERIFY(alpha.compare(beta, Qt::CaseInsensitive) < 0);
+ QVERIFY(alpha.compare(beta, Qt::CaseSensitive) > 0);
+}
+
+void tst_QByteArrayView::std_stringview_conversion()
+{
+ static_assert(std::is_convertible_v<QByteArrayView, std::string_view>);
+
+ QByteArrayView bav;
+ std::string_view sv(bav);
+ QCOMPARE(sv, std::string_view());
+
+ bav = "";
+ sv = bav;
+ QCOMPARE(bav.size(), 0);
+ QCOMPARE(sv.size(), size_t(0));
+ QCOMPARE(sv, std::string_view());
+
+ bav = "Hello";
+ sv = bav;
+ QCOMPARE(sv, std::string_view("Hello"));
+
+ bav = QByteArrayView::fromArray("Hello\0world");
+ sv = bav;
+ QCOMPARE(bav.size(), 12);
+ QCOMPARE(sv.size(), size_t(12));
+ QCOMPARE(sv, std::string_view("Hello\0world", 12));
+}
+
+QTEST_APPLESS_MAIN(tst_QByteArrayView)
+#include "tst_qbytearrayview.moc"