summaryrefslogtreecommitdiffstats
path: root/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2020-10-30 11:15:19 +0100
committerLars Knoll <lars.knoll@qt.io>2020-11-04 11:21:32 +0100
commit50ec3252ac5d61a13fab01801ef42729d6f3a7c6 (patch)
tree7665fa8db669a65d772e322ba6bd7f8160bff781 /tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
parent90fadbb3656eaf5db0aa9341f2ef4b2d44156446 (diff)
Do not move data around on insert neither
The while insertion logic will need further work to make it more efficient. Currently it does use copy construction and assignment for internal moving instead of move operations. Change-Id: I7ae3094daa43a44629d8fa89ab6562c2a21b6cbd Reviewed-by: MÃ¥rten Nordheim <marten.nordheim@qt.io> Reviewed-by: Andrei Golubev <andrei.golubev@qt.io> Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
Diffstat (limited to 'tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp')
-rw-r--r--tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp207
1 files changed, 4 insertions, 203 deletions
diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
index b1ce9a9a46..497f582c10 100644
--- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
+++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp
@@ -89,8 +89,6 @@ private slots:
void exceptionSafetyPrimitives_destructor();
void exceptionSafetyPrimitives_mover();
void exceptionSafetyPrimitives_displacer();
- void moveNonPod_data();
- void moveNonPod();
#endif
};
@@ -922,8 +920,10 @@ void tst_QArrayData::arrayOps()
// Insertion at begin (prepend) caused the elements to move, meaning
// that instead of being displaced, newly added elements got constructed
// in uninitialized memory with DefaultConstructed | CopyConstructed
- QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed
- | CountedObject::CopyConstructed);
+ // ### QArrayData::insert does copy assign some of the values, so this test doesn't
+ // work
+// QCOMPARE(int(vo[i].flags), CountedObject::DefaultConstructed
+// | CountedObject::CopyConstructed);
}
for (int i = 5; i < 15; ++i) {
@@ -2840,205 +2840,6 @@ void tst_QArrayData::exceptionSafetyPrimitives_displacer()
}
}
}
-
-struct GenericThrowingType
-{
- std::shared_ptr<int> data = std::shared_ptr<int>(new int(42)); // helper for double free
- ThrowingType throwingData = ThrowingType(0);
- GenericThrowingType(int id = 0) : throwingData(id)
- {
- QVERIFY(data.use_count() > 0);
- }
-
- ~GenericThrowingType()
- {
- // if we're in dtor but use_count is 0, it's double free
- QVERIFY(data.use_count() > 0);
- }
-
- enum MoveCase {
- MoveRightNoOverlap = 0,
- MoveRightOverlap = 1,
- MoveLeftNoOverlap = 2,
- MoveLeftOverlap = 3,
- };
-
- enum ThrowCase {
- ThrowInDtor = 0,
- ThrowInUninitializedRegion = 1,
- ThrowInOverlapRegion = 2,
- };
-};
-
-struct PublicGenericMoveOps : QtPrivate::QCommonArrayOps<GenericThrowingType>
-{
- template<typename GrowthTag>
- void public_moveInGrowthDirection(GrowthTag tag, qsizetype futureGrowth)
- {
- static_assert(!QTypeInfo<GenericThrowingType>::isRelocatable);
- using MoveOps = QtPrivate::QCommonArrayOps<GenericThrowingType>::GenericMoveOps;
- MoveOps::moveInGrowthDirection(tag, this, futureGrowth);
- }
-};
-
-void tst_QArrayData::moveNonPod_data()
-{
- QTest::addColumn<GenericThrowingType::MoveCase>("moveCase");
- QTest::addColumn<GenericThrowingType::ThrowCase>("throwCase");
-
- // Throwing in dtor
- QTest::newRow("throw-in-dtor-move-right-no-overlap")
- << GenericThrowingType::MoveRightNoOverlap << GenericThrowingType::ThrowInDtor;
- QTest::newRow("throw-in-dtor-move-right-overlap")
- << GenericThrowingType::MoveRightOverlap << GenericThrowingType::ThrowInDtor;
- QTest::newRow("throw-in-dtor-move-left-no-overlap")
- << GenericThrowingType::MoveLeftNoOverlap << GenericThrowingType::ThrowInDtor;
- QTest::newRow("throw-in-dtor-move-left-overlap")
- << GenericThrowingType::MoveLeftOverlap << GenericThrowingType::ThrowInDtor;
-
- // Throwing in uninitialized region
- QTest::newRow("throw-in-uninit-region-move-right-no-overlap")
- << GenericThrowingType::MoveRightNoOverlap
- << GenericThrowingType::ThrowInUninitializedRegion;
- QTest::newRow("throw-in-uninit-region-move-right-overlap")
- << GenericThrowingType::MoveRightOverlap << GenericThrowingType::ThrowInUninitializedRegion;
- QTest::newRow("throw-in-uninit-region-move-left-no-overlap")
- << GenericThrowingType::MoveLeftNoOverlap
- << GenericThrowingType::ThrowInUninitializedRegion;
- QTest::newRow("throw-in-uninit-region-move-left-overlap")
- << GenericThrowingType::MoveLeftOverlap << GenericThrowingType::ThrowInUninitializedRegion;
-
- // Throwing in overlap region
- QTest::newRow("throw-in-overlap-region-move-right-overlap")
- << GenericThrowingType::MoveRightOverlap << GenericThrowingType::ThrowInOverlapRegion;
- QTest::newRow("throw-in-overlap-region-move-left-overlap")
- << GenericThrowingType::MoveLeftOverlap << GenericThrowingType::ThrowInOverlapRegion;
-}
-
-void tst_QArrayData::moveNonPod()
-{
- // Assume that non-throwing moves perform correctly. Otherwise, all previous
- // tests would've failed. Test only what happens when exceptions are thrown.
-
- QFETCH(GenericThrowingType::MoveCase, moveCase);
- QFETCH(GenericThrowingType::ThrowCase, throwCase);
-
- struct WatcherScope
- {
- WatcherScope() { throwingTypeWatcher().watch = true; }
- ~WatcherScope()
- {
- throwingTypeWatcher().watch = false;
- throwingTypeWatcher().destroyedIds.clear();
- }
- };
-
- const auto cast = [] (auto &dataPointer) {
- return static_cast<PublicGenericMoveOps*>(std::addressof(dataPointer));
- };
-
- const auto setThrowingFlag = [throwCase] () {
- switch (throwCase) {
- case GenericThrowingType::ThrowInDtor: ThrowingType::throwOnceInDtor = 2; break;
- case GenericThrowingType::ThrowInUninitializedRegion: ThrowingType::throwOnce = 2; break;
- case GenericThrowingType::ThrowInOverlapRegion: ThrowingType::throwOnce = 3; break;
- default: QFAIL("Unknown throwCase");
- }
- };
-
- const auto checkExceptionText = [throwCase] (const char *what) {
- if (throwCase == GenericThrowingType::ThrowInDtor) {
- QCOMPARE(std::string(what), ThrowingType::throwStringDtor);
- } else {
- QCOMPARE(std::string(what), ThrowingType::throwString);
- }
- };
-
- const auto checkNoMemoryLeaks = [throwCase] (size_t extraDestroyedElements = 0) {
- const size_t destroyedElementsCount = throwingTypeWatcher().destroyedIds.size();
- switch (throwCase) {
- case GenericThrowingType::ThrowInDtor:
- // 2 elements from uinitialized region + 2 elements from old range + extra if no overlap
- QCOMPARE(destroyedElementsCount, 2u + 2u + extraDestroyedElements);
- break;
- case GenericThrowingType::ThrowInUninitializedRegion:
- // always 1 element from uninitialized region
- QCOMPARE(destroyedElementsCount, 1u);
- break;
- case GenericThrowingType::ThrowInOverlapRegion:
- // always 2 elements from uninitialized region
- QCOMPARE(destroyedElementsCount, 2u);
- break;
- default: QFAIL("Unknown throwCase");
- }
- };
-
- switch (moveCase) {
- case GenericThrowingType::MoveRightNoOverlap : { // moving right without overlap
- auto storage = createDataPointer<GenericThrowingType>(20, 3);
- QVERIFY(storage.freeSpaceAtEnd() > 3);
-
- WatcherScope scope; Q_UNUSED(scope);
- try {
- setThrowingFlag();
- cast(storage)->public_moveInGrowthDirection(QtPrivate::GrowsForwardTag{}, 4);
- QFAIL("Unreachable line!");
- } catch (const std::runtime_error &e) {
- checkExceptionText(e.what());
- }
- checkNoMemoryLeaks(1);
- break;
- }
- case GenericThrowingType::MoveRightOverlap: { // moving right with overlap
- auto storage = createDataPointer<GenericThrowingType>(20, 3);
- QVERIFY(storage.freeSpaceAtEnd() > 3);
-
- WatcherScope scope; Q_UNUSED(scope);
- try {
- setThrowingFlag();
- cast(storage)->public_moveInGrowthDirection(QtPrivate::GrowsForwardTag{}, 2);
- QFAIL("Unreachable line!");
- } catch (const std::runtime_error &e) {
- checkExceptionText(e.what());
- }
- checkNoMemoryLeaks();
- break;
- }
- case GenericThrowingType::MoveLeftNoOverlap: { // moving left without overlap
- auto storage = createDataPointer<GenericThrowingType>(20, 2);
- storage->insert(storage.begin(), 1, GenericThrowingType(42));
- QVERIFY(storage.freeSpaceAtBegin() > 3);
-
- WatcherScope scope; Q_UNUSED(scope);
- try {
- setThrowingFlag();
- cast(storage)->public_moveInGrowthDirection(QtPrivate::GrowsBackwardsTag{}, 4);
- QFAIL("Unreachable line!");
- } catch (const std::runtime_error &e) {
- checkExceptionText(e.what());
- }
- checkNoMemoryLeaks(1);
- break;
- }
- case GenericThrowingType::MoveLeftOverlap: {
- auto storage = createDataPointer<GenericThrowingType>(20, 2);
- storage->insert(storage.begin(), 1, GenericThrowingType(42));
- QVERIFY(storage.freeSpaceAtBegin() > 3);
-
- WatcherScope scope; Q_UNUSED(scope);
- try {
- setThrowingFlag();
- cast(storage)->public_moveInGrowthDirection(QtPrivate::GrowsBackwardsTag{}, 2);
- QFAIL("Unreachable line!");
- } catch (const std::runtime_error &e) {
- checkExceptionText(e.what());
- }
- checkNoMemoryLeaks();
- break;
- }
- default: QFAIL("Unknown moveCase");
- };
-}
#endif // QT_NO_EXCEPTIONS
QTEST_APPLESS_MAIN(tst_QArrayData)