diff options
author | Tor Arne Vestbø <tor.arne.vestbo@qt.io> | 2017-05-02 19:23:13 +0200 |
---|---|---|
committer | Fabian Kosmale <fabian.kosmale@qt.io> | 2020-03-17 10:01:04 +0100 |
commit | 165de1002719175c75df61913d36c2189538a84b (patch) | |
tree | 39f3be146633ad2f25b1a55d000edb1475149082 /tests/auto/corelib/tools | |
parent | 7ef382649754c261ca9eb99dd50b67050e748efb (diff) |
Introduce helper class QTaggedPointer
Useful for attaching small bits of information in the alignment bits of
a naked pointer. For use in the new property system as well as in
qtdeclarative (where currently a similar class exists as private API).
Change-Id: Idf9b93e714e15129f302e16425dbeda94bcd207b
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'tests/auto/corelib/tools')
-rw-r--r-- | tests/auto/corelib/tools/.prev_CMakeLists.txt | 45 | ||||
-rw-r--r-- | tests/auto/corelib/tools/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtaggedpointer/.gitignore | 1 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt | 12 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtaggedpointer/qtaggedpointer.pro | 4 | ||||
-rw-r--r-- | tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp | 400 | ||||
-rw-r--r-- | tests/auto/corelib/tools/tools.pro | 1 |
7 files changed, 464 insertions, 0 deletions
diff --git a/tests/auto/corelib/tools/.prev_CMakeLists.txt b/tests/auto/corelib/tools/.prev_CMakeLists.txt new file mode 100644 index 0000000000..5350c29b79 --- /dev/null +++ b/tests/auto/corelib/tools/.prev_CMakeLists.txt @@ -0,0 +1,45 @@ +# Generated from tools.pro. + +add_subdirectory(collections) +add_subdirectory(containerapisymmetry) +add_subdirectory(qalgorithms) +add_subdirectory(qarraydata) +add_subdirectory(qbitarray) +add_subdirectory(qcache) +add_subdirectory(qcommandlineparser) +add_subdirectory(qcontiguouscache) +add_subdirectory(qcryptographichash) +add_subdirectory(qeasingcurve) +add_subdirectory(qexplicitlyshareddatapointer) +add_subdirectory(qflatmap) +add_subdirectory(qfreelist) +add_subdirectory(qhash) +add_subdirectory(qhashfunctions) +add_subdirectory(qline) +add_subdirectory(qmakearray) +add_subdirectory(qmap) +add_subdirectory(qmargins) +add_subdirectory(qmessageauthenticationcode) +add_subdirectory(qoffsetstringarray) +add_subdirectory(qpair) +add_subdirectory(qpoint) +add_subdirectory(qpointf) +add_subdirectory(qqueue) +add_subdirectory(qrect) +add_subdirectory(qringbuffer) +add_subdirectory(qscopedpointer) +add_subdirectory(qscopedvaluerollback) +add_subdirectory(qscopeguard) +add_subdirectory(qtaggedpointer) +add_subdirectory(qset) +add_subdirectory(qsharedpointer) +add_subdirectory(qsize) +add_subdirectory(qsizef) +add_subdirectory(qstl) +add_subdirectory(qtimeline) +add_subdirectory(qvarlengtharray) +add_subdirectory(qvector) +add_subdirectory(qversionnumber) +if(APPLE) + add_subdirectory(qmacautoreleasepool) +endif() diff --git a/tests/auto/corelib/tools/CMakeLists.txt b/tests/auto/corelib/tools/CMakeLists.txt index f1967c3664..2a7025f97c 100644 --- a/tests/auto/corelib/tools/CMakeLists.txt +++ b/tests/auto/corelib/tools/CMakeLists.txt @@ -34,6 +34,7 @@ add_subdirectory(qringbuffer) add_subdirectory(qscopedpointer) add_subdirectory(qscopedvaluerollback) add_subdirectory(qscopeguard) +add_subdirectory(qtaggedpointer) add_subdirectory(qset) # add_subdirectory(qsharedpointer) # special case not ported add_subdirectory(qsize) diff --git a/tests/auto/corelib/tools/qtaggedpointer/.gitignore b/tests/auto/corelib/tools/qtaggedpointer/.gitignore new file mode 100644 index 0000000000..d027eb73b2 --- /dev/null +++ b/tests/auto/corelib/tools/qtaggedpointer/.gitignore @@ -0,0 +1 @@ +tst_qtaggedpointer diff --git a/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt b/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt new file mode 100644 index 0000000000..1057e5ebe5 --- /dev/null +++ b/tests/auto/corelib/tools/qtaggedpointer/CMakeLists.txt @@ -0,0 +1,12 @@ +# Generated from qtaggedpointer.pro. + +##################################################################### +## tst_qtaggedpointer Test: +##################################################################### + +qt_add_test(tst_qtaggedpointer + SOURCES + tst_qtaggedpointer.cpp + PUBLIC_LIBRARIES + Qt::CorePrivate +) diff --git a/tests/auto/corelib/tools/qtaggedpointer/qtaggedpointer.pro b/tests/auto/corelib/tools/qtaggedpointer/qtaggedpointer.pro new file mode 100644 index 0000000000..48bc503c56 --- /dev/null +++ b/tests/auto/corelib/tools/qtaggedpointer/qtaggedpointer.pro @@ -0,0 +1,4 @@ +CONFIG += testcase +TARGET = tst_qtaggedpointer +QT = core-private testlib +SOURCES = tst_qtaggedpointer.cpp diff --git a/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp new file mode 100644 index 0000000000..36308d61bc --- /dev/null +++ b/tests/auto/corelib/tools/qtaggedpointer/tst_qtaggedpointer.cpp @@ -0,0 +1,400 @@ +/**************************************************************************** +** +** 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 <QtTest/QtTest> +#include <QtCore/qtaggedpointer.h> + +class tst_QTaggedPointer : public QObject +{ + Q_OBJECT + +private Q_SLOTS: + void construction(); + void dereferenceOperator(); + void pointerOperator(); + void negationOperator(); + void operatorBool(); + void comparison(); + void tag(); + void objectMember(); + void customTagType(); +}; + +void tst_QTaggedPointer::construction() +{ + { + QTaggedPointer<int> p; + QCOMPARE(p.pointer(), nullptr); + QVERIFY(!p.tag()); + } + { + QTaggedPointer<int> p(nullptr, 0x1); + QCOMPARE(p.pointer(), nullptr); + QCOMPARE(p.tag(), quintptr(0x1)); + } + { + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data()); + QCOMPARE(p.pointer(), rawPointer.data()); + QVERIFY(!p.tag()); + } + { + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QCOMPARE(p.pointer(), rawPointer.data()); + QCOMPARE(p.tag(), quintptr(0x1)); + } +} + +class AbstractClass +{ +public: + virtual ~AbstractClass() {} + virtual int member() const = 0; +}; + +class SubClass : public AbstractClass +{ +public: + int member() const { return 5; } +}; + +void tst_QTaggedPointer::dereferenceOperator() +{ + /* Dereference a basic value. */ + { + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data()); + const int value = *p; + QCOMPARE(value, 5); + } + + /* Dereference a basic value with tag. */ + { + QScopedPointer<int> rawPointer(new int(5)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + const int value = *p; + QCOMPARE(value, 5); + } + + /* Dereference a pointer to an abstract class. This verifies + * that the operator returns a reference, when compiling + * with MSVC 2005. */ + { + QScopedPointer<SubClass> ptr(new SubClass()); + QTaggedPointer<AbstractClass> p(ptr.data()); + QCOMPARE((*p).member(), 5); + } + + /* The operator should be const. */ + { + QScopedPointer<int> rawPointer(new int(5)); + const QTaggedPointer<int> p(rawPointer.data()); + *p; + } + + /* A reference should be returned, not a value. */ + { + QScopedPointer<int> rawPointer(new int(5)); + const QTaggedPointer<int> p(rawPointer.data()); + Q_UNUSED(static_cast<int &>(*p)); + } + + /* Instantiated on a const object, the returned object is a const reference. */ + { + QScopedPointer<int> rawPointer(new int(5)); + const QTaggedPointer<const int> p(rawPointer.data()); + Q_UNUSED(static_cast<const int &>(*p)); + } +} + +class Value +{ +public: + int value; +}; + +void tst_QTaggedPointer::pointerOperator() +{ + { + QScopedPointer<Value> valuePtr(new Value{5}); + QTaggedPointer<Value> p(valuePtr.data()); + QCOMPARE(p->value, 5); + } + + { + QScopedPointer<Value> valuePtr(new Value{5}); + QTaggedPointer<Value> p(valuePtr.data(), 0x1); + QCOMPARE(p->value, 5); + } + + /* The operator should be const. */ + { + QScopedPointer<Value> valuePtr(new Value{5}); + const QTaggedPointer<Value> p(valuePtr.data()); + QVERIFY(p->value); + } +} + +void tst_QTaggedPointer::negationOperator() +{ + /* Invoke on default constructed value. */ + { + QTaggedPointer<int> p; + QVERIFY(!p); + } + + /* Invoke on nullptr value with tag. */ + { + QTaggedPointer<int> p(nullptr, 0x1); + QVERIFY(!p); + } + + /* Invoke on a value. */ + { + QScopedPointer<int> rawPointer(new int(2)); + QTaggedPointer<int> p(rawPointer.data()); + QCOMPARE(!p, false); + } + + /* Invoke on a value with tag. */ + { + QScopedPointer<int> rawPointer(new int(2)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QCOMPARE(!p, false); + } + + /* The signature should be const. */ + { + const QTaggedPointer<int> p; + !p; + } + + /* The return value should be bool. */ + { + const QTaggedPointer<int> p; + Q_UNUSED(static_cast<bool>(!p)); + } +} + +void tst_QTaggedPointer::operatorBool() +{ + /* Invoke on default constructed value. */ + { + QTaggedPointer<int> p; + QCOMPARE(bool(p), false); + } + + /* Invoke on nullptr value with tag. */ + { + QTaggedPointer<int> p(nullptr, 0x1); + QCOMPARE(bool(p), false); + } + + /* Invoke on active value. */ + { + QScopedPointer<int> rawPointer(new int(3)); + QTaggedPointer<int> p(rawPointer.data()); + QVERIFY(p); + } + + /* Invoke on active value with tag. */ + { + QScopedPointer<int> rawPointer(new int(3)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QVERIFY(p); + } + + /* The signature should be const and return bool. */ + { + const QTaggedPointer<int> p; + (void)static_cast<bool>(p); + } +} + +template <class A1, class A2, class B> +void comparisonTest(const A1 &a1, const A2 &a2, const B &b) +{ + // test equality on equal pointers + QVERIFY(a1 == a2); + QVERIFY(a2 == a1); + + // test inequality on equal pointers + QVERIFY(!(a1 != a2)); + QVERIFY(!(a2 != a1)); + + // test equality on unequal pointers + QVERIFY(!(a1 == b)); + QVERIFY(!(a2 == b)); + QVERIFY(!(b == a1)); + QVERIFY(!(b == a2)); + + // test inequality on unequal pointers + QVERIFY(b != a1); + QVERIFY(b != a2); + QVERIFY(a1 != b); + QVERIFY(a2 != b); +} + +void tst_QTaggedPointer::comparison() +{ + QScopedPointer<int> a(new int(5)); + + { + QTaggedPointer<int> a1(a.data()); + QTaggedPointer<int> a2(a.data()); + QScopedPointer<int> rawPointer(new int(6)); + QTaggedPointer<int> b(rawPointer.data()); + + comparisonTest(a1, a1, b); + comparisonTest(a2, a2, b); + comparisonTest(a1, a2, b); + } + { + QTaggedPointer<int> a1(a.data(), 0x1); + QTaggedPointer<int> a2(a.data(), 0x1); + QScopedPointer<int> rawPointer(new int(6)); + QTaggedPointer<int> b(rawPointer.data(), 0x1); + + comparisonTest(a1, a1, b); + comparisonTest(a2, a2, b); + comparisonTest(a1, a2, b); + } + { + QTaggedPointer<int> a1(a.data(), 0x1); + QTaggedPointer<int> a2(a.data(), 0x2); + QScopedPointer<int> rawPointer(new int(6)); + QTaggedPointer<int> b(rawPointer.data(), 0x2); + + comparisonTest(a1, a1, b); + comparisonTest(a2, a2, b); + comparisonTest(a1, a2, b); + } + { + QTaggedPointer<int> p; + QVERIFY(p.isNull()); + QVERIFY(p == nullptr); + QVERIFY(nullptr == p); + } + { + QTaggedPointer<int> p(nullptr, 0x1); + QVERIFY(p.isNull()); + QVERIFY(p == nullptr); + QVERIFY(nullptr == p); + } + { + QScopedPointer<int> rawPointer(new int(42)); + QTaggedPointer<int> p(rawPointer.data()); + QVERIFY(!p.isNull()); + QVERIFY(p != nullptr); + QVERIFY(nullptr != p); + } + { + QScopedPointer<int> rawPointer(new int(42)); + QTaggedPointer<int> p(rawPointer.data(), 0x1); + QVERIFY(!p.isNull()); + QVERIFY(p != nullptr); + QVERIFY(nullptr != p); + } +} + +void tst_QTaggedPointer::tag() +{ + QScopedPointer<int> rawPointer(new int(3)); + QTaggedPointer<int> p(rawPointer.data()); + QCOMPARE(*p.pointer(), 3); + QVERIFY(!p.tag()); + + p.setTag(0x1); + QCOMPARE(p.tag(), 0x1); + + p.setTag(0x2); + QCOMPARE(p.tag(), 0x2); +} + +struct Foo +{ + Foo() : p(nullptr) {} + Foo(const Foo &other) : p(other.p) {} + Foo &operator=(const Foo &other) { + p = other.p; + return *this; + } + QTaggedPointer<int> p; +}; + +void tst_QTaggedPointer::objectMember() +{ + QScopedPointer<int> rawPointer(new int(42)); + Foo f; + f.p = QTaggedPointer<int>(rawPointer.data(), 0x1); + + Foo f2(f); + QCOMPARE(f2.p.pointer(), f.p.pointer()); + QCOMPARE(f2.p.tag(), f.p.tag()); + + Foo f3 = f; + QCOMPARE(f3.p.pointer(), f.p.pointer()); + QCOMPARE(f3.p.tag(), f.p.tag()); +} + +class Bar +{ + Q_GADGET +public: + enum Tag { + NoTag = 0, + FirstTag = 1, + SecondTag = 2 + }; + Q_DECLARE_FLAGS(Tags, Tag) + Q_FLAG(Tags) + + int value; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(Bar::Tags) + +void tst_QTaggedPointer::customTagType() +{ + QScopedPointer<Bar> barPtr(new Bar{5}); + typedef QTaggedPointer<Bar, Bar::Tags> TaggedBar; + TaggedBar p(barPtr.data()); + QCOMPARE(p->value, 5); + QVERIFY(TaggedBar::maximumTag()); + + QVERIFY(!p.tag()); + QCOMPARE(p.tag(), Bar::NoTag); + + p.setTag(Bar::FirstTag | Bar::SecondTag); + QCOMPARE(p->value, 5); + QCOMPARE(p.tag(), Bar::FirstTag | Bar::SecondTag); +} + +QTEST_MAIN(tst_QTaggedPointer) +#include "tst_qtaggedpointer.moc" diff --git a/tests/auto/corelib/tools/tools.pro b/tests/auto/corelib/tools/tools.pro index e51be90100..21dfdf8c47 100644 --- a/tests/auto/corelib/tools/tools.pro +++ b/tests/auto/corelib/tools/tools.pro @@ -30,6 +30,7 @@ SUBDIRS=\ qscopedpointer \ qscopedvaluerollback \ qscopeguard \ + qtaggedpointer \ qset \ qsharedpointer \ qsize \ |