summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib
diff options
context:
space:
mode:
authorSona Kurazyan <sona.kurazyan@qt.io>2020-06-07 18:41:41 +0200
committerSona Kurazyan <sona.kurazyan@qt.io>2020-07-08 08:45:49 +0200
commit631127126cc14e7c01cc611532b3256b58785670 (patch)
treea89608313761f045129f6579d5c96d781d64ff31 /tests/auto/corelib
parenta55e938fb41dfb781cdef6a4e24961a272d2dbab (diff)
Introduce QByteArrayView
Created a QByteArrayView in symmetry with QStringView. Added the basic tests symmetrical to QStringView tests. Moved the implementations of non-modifying methods of QByteArray to namespace QtPrivate, to be reused inline from both QByteArray and QByteArrayView. Changed QByteArray's counterparts of those methods to take QByteArrayView as argument instead of QByteArray. Removed QByteArray's operator QNoImplicitBoolCast(), because it was causing ambiguity when calling those methods with QByteArray argument (it was there to perevnt if(!ba)/if(ba) from compiling, but currently that would be ambiguous and won't compile anyway). [ChangeLog][QtCore][QByteArrayView] New class. Task-number: QTBUG-84321 Change-Id: I05f92e654cf65c95f2bb31b9c9018746ac110426 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'tests/auto/corelib')
-rw-r--r--tests/auto/corelib/text/CMakeLists.txt1
-rw-r--r--tests/auto/corelib/text/qbytearrayview/CMakeLists.txt10
-rw-r--r--tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro4
-rw-r--r--tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp595
-rw-r--r--tests/auto/corelib/text/text.pro1
5 files changed, 611 insertions, 0 deletions
diff --git a/tests/auto/corelib/text/CMakeLists.txt b/tests/auto/corelib/text/CMakeLists.txt
index 1988bcc28d..0c36f1e088 100644
--- a/tests/auto/corelib/text/CMakeLists.txt
+++ b/tests/auto/corelib/text/CMakeLists.txt
@@ -4,6 +4,7 @@ add_subdirectory(qbytearray)
add_subdirectory(qbytearrayapisymmetry)
add_subdirectory(qbytearraylist)
add_subdirectory(qbytearraymatcher)
+add_subdirectory(qbytearrayview)
add_subdirectory(qbytedatabuffer)
add_subdirectory(qchar)
add_subdirectory(qcollator)
diff --git a/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt b/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
new file mode 100644
index 0000000000..34476b8246
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Generated from qbytearrayview.pro.
+
+#####################################################################
+## tst_qbytearrayview Test:
+#####################################################################
+
+qt_add_test(tst_qbytearrayview
+ SOURCES
+ tst_qbytearrayview.cpp
+)
diff --git a/tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro b/tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro
new file mode 100644
index 0000000000..23d0aed959
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/qbytearrayview.pro
@@ -0,0 +1,4 @@
+CONFIG += testcase
+TARGET = tst_qbytearrayview
+QT = core testlib
+SOURCES += tst_qbytearrayview.cpp
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..c1d80b47dc
--- /dev/null
+++ b/tests/auto/corelib/text/qbytearrayview/tst_qbytearrayview.cpp
@@ -0,0 +1,595 @@
+/****************************************************************************
+**
+** Copyright (C) 2020 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QByteArrayView>
+
+#include <QTest>
+
+// for negative testing (can't convert from)
+#include <deque>
+#include <list>
+
+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:
+ void constExpr() const;
+ void basics() const;
+ void literals() 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;
+
+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 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 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 QByteArrayView bv2(bv.data(), bv.data() + bv.size());
+ static_assert(!bv2.isNull());
+ static_assert(!bv2.empty());
+ static_assert(bv2.size() == 5);
+ }
+ {
+ 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');
+ }
+ {
+ 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 char *null = nullptr;
+ constexpr QByteArrayView bv(null);
+ static_assert(bv.isNull());
+ static_assert(bv.isEmpty());
+ static_assert(bv.size() == 0);
+ }
+}
+
+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));
+}
+
+void tst_QByteArrayView::literals() const
+{
+ const char hello[] = "Hello";
+
+ 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);
+}
+
+void tst_QByteArrayView::literalsWithInternalNulls() const
+{
+ const char withnull[] = "a\0zzz";
+
+ // these are different results
+ QCOMPARE(size_t(QByteArrayView(withnull).size()), sizeof(withnull)/sizeof(withnull[0]) - 1);
+ QCOMPARE(QByteArrayView(withnull + 0).size(), 1);
+
+ QByteArrayView nulled(withnull);
+ 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.endsWith("zz"));
+ QVERIFY(nulled.contains("z"));
+ QVERIFY(nulled.contains("\0z"));
+ QVERIFY(!nulled.contains("\0y"));
+ QCOMPARE(nulled.first(5), withnull);
+ QCOMPARE(nulled.last(5), withnull);
+ QCOMPARE(nulled.sliced(0), withnull);
+ QCOMPARE(nulled.sliced(2, 2), "zz");
+ QCOMPARE(nulled.chopped(2), "a\0z");
+ QVERIFY(nulled.chopped(2) != "a\0y");
+ QCOMPARE(nulled.count('z'), 3);
+
+ const char nullfirst[] = "\0buzz";
+ QByteArrayView fromnull(nullfirst);
+ QVERIFY(!fromnull.isEmpty());
+
+ const char nullNotEnd[] = { 'b', 'o', 'w', '\0', 'a', 'f', 't', 'z' };
+ QByteArrayView midNull(nullNotEnd);
+ QCOMPARE(midNull.back(), 't');
+}
+
+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(empty).size(), 0);
+ QCOMPARE(static_cast<const void*>(QByteArrayView(empty).data()),
+ static_cast<const void*>(empty));
+
+ QVERIFY(QByteArrayView(null).isNull());
+ QVERIFY(QByteArrayView(null).isEmpty());
+ QVERIFY(QByteArrayView(empty).isEmpty());
+ QVERIFY(!QByteArrayView(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);
+}
+
+QTEST_APPLESS_MAIN(tst_QByteArrayView)
+#include "tst_qbytearrayview.moc"
diff --git a/tests/auto/corelib/text/text.pro b/tests/auto/corelib/text/text.pro
index bad5f6d61a..272bcb1013 100644
--- a/tests/auto/corelib/text/text.pro
+++ b/tests/auto/corelib/text/text.pro
@@ -5,6 +5,7 @@ SUBDIRS = \
qbytearrayapisymmetry \
qbytearraylist \
qbytearraymatcher \
+ qbytearrayview \
qbytedatabuffer \
qchar \
qcollator \