/**************************************************************************** ** ** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins ** 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 #include /*! \class tst_QScopeGuard \internal \since 5.11 \brief Tests class QScopeGuard and function qScopeGuard */ class tst_QScopeGuard : public QObject { Q_OBJECT private Q_SLOTS: void construction(); void constructionFromLvalue(); void constructionFromRvalue(); void leavingScope(); void exceptions(); }; void func() { } int intFunc() { return 0; } [[nodiscard]] int noDiscardFunc() { return 0; } struct Callable { Callable() { } Callable(const Callable &other) { Q_UNUSED(other); ++copied; } Callable(Callable &&other) { Q_UNUSED(other); ++moved; } void operator()() { } static int copied; static int moved; static void resetCounts() { copied = 0; moved = 0; } }; int Callable::copied = 0; int Callable::moved = 0; static int s_globalState = 0; void tst_QScopeGuard::construction() { QScopeGuard fromLambda([] { }); QScopeGuard fromFunction(func); QScopeGuard fromFunctionPointer(&func); QScopeGuard fromNonVoidFunction(intFunc); QScopeGuard fromNoDiscardFunction(noDiscardFunc); #ifndef __apple_build_version__ QScopeGuard fromStdFunction{std::function(func)}; std::function stdFunction(func); QScopeGuard fromNamedStdFunction(stdFunction); #endif } void tst_QScopeGuard::constructionFromLvalue() { Callable::resetCounts(); { Callable callable; QScopeGuard guard(callable); } QCOMPARE(Callable::copied, 1); QCOMPARE(Callable::moved, 0); Callable::resetCounts(); { Callable callable; auto guard = qScopeGuard(callable); } QCOMPARE(Callable::copied, 1); QCOMPARE(Callable::moved, 0); } void tst_QScopeGuard::constructionFromRvalue() { Callable::resetCounts(); { Callable callable; QScopeGuard guard(std::move(callable)); } QCOMPARE(Callable::copied, 0); QCOMPARE(Callable::moved, 1); Callable::resetCounts(); { Callable callable; auto guard = qScopeGuard(std::move(callable)); } QCOMPARE(Callable::copied, 0); QCOMPARE(Callable::moved, 1); } void tst_QScopeGuard::leavingScope() { auto cleanup = qScopeGuard([] { s_globalState++; QCOMPARE(s_globalState, 3); }); QCOMPARE(s_globalState, 0); { auto cleanup = qScopeGuard([] { s_globalState++; }); QCOMPARE(s_globalState, 0); } QCOMPARE(s_globalState, 1); s_globalState++; } void tst_QScopeGuard::exceptions() { s_globalState = 0; bool caught = false; QT_TRY { auto cleanup = qScopeGuard([] { s_globalState++; }); QT_THROW(std::bad_alloc()); //if Qt compiled without exceptions this is noop s_globalState = 100; } QT_CATCH(...) { caught = true; QCOMPARE(s_globalState, 1); } QVERIFY((caught && s_globalState == 1) || (!caught && s_globalState == 101)); } QTEST_MAIN(tst_QScopeGuard) #include "tst_qscopeguard.moc"