summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/text/qbytearrayview
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/corelib/text/qbytearrayview')
-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
3 files changed, 609 insertions, 0 deletions
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"