1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2018 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Sérgio Martins <sergio.martins@kdab.com> |
4 | ** Copyright (C) 2019 The Qt Company Ltd. |
5 | ** Contact: https://www.qt.io/licensing/ |
6 | ** |
7 | ** This file is part of the test suite of the Qt Toolkit. |
8 | ** |
9 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
10 | ** Commercial License Usage |
11 | ** Licensees holding valid commercial Qt licenses may use this file in |
12 | ** accordance with the commercial license agreement provided with the |
13 | ** Software or, alternatively, in accordance with the terms contained in |
14 | ** a written agreement between you and The Qt Company. For licensing terms |
15 | ** and conditions see https://www.qt.io/terms-conditions. For further |
16 | ** information use the contact form at https://www.qt.io/contact-us. |
17 | ** |
18 | ** GNU General Public License Usage |
19 | ** Alternatively, this file may be used under the terms of the GNU |
20 | ** General Public License version 3 as published by the Free Software |
21 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
22 | ** included in the packaging of this file. Please review the following |
23 | ** information to ensure the GNU General Public License requirements will |
24 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
25 | ** |
26 | ** $QT_END_LICENSE$ |
27 | ** |
28 | ****************************************************************************/ |
29 | |
30 | #include <QtTest/QtTest> |
31 | #include <QtCore/QScopeGuard> |
32 | |
33 | /*! |
34 | \class tst_QScopeGuard |
35 | \internal |
36 | \since 5.11 |
37 | \brief Tests class QScopeGuard and function qScopeGuard |
38 | |
39 | */ |
40 | class tst_QScopeGuard : public QObject |
41 | { |
42 | Q_OBJECT |
43 | |
44 | private Q_SLOTS: |
45 | void construction(); |
46 | void constructionFromLvalue(); |
47 | void constructionFromRvalue(); |
48 | void leavingScope(); |
49 | void exceptions(); |
50 | }; |
51 | |
52 | void func() |
53 | { |
54 | } |
55 | |
56 | int intFunc() |
57 | { |
58 | return 0; |
59 | } |
60 | |
61 | Q_REQUIRED_RESULT int noDiscardFunc() |
62 | { |
63 | return 0; |
64 | } |
65 | |
66 | struct Callable |
67 | { |
68 | Callable() { } |
69 | Callable(const Callable &other) |
70 | { |
71 | Q_UNUSED(other); |
72 | ++copied; |
73 | } |
74 | Callable(Callable &&other) |
75 | { |
76 | Q_UNUSED(other); |
77 | ++moved; |
78 | } |
79 | void operator()() { } |
80 | |
81 | static int copied; |
82 | static int moved; |
83 | static void resetCounts() |
84 | { |
85 | copied = 0; |
86 | moved = 0; |
87 | } |
88 | }; |
89 | |
90 | int Callable::copied = 0; |
91 | int Callable::moved = 0; |
92 | |
93 | static int s_globalState = 0; |
94 | |
95 | void tst_QScopeGuard::construction() |
96 | { |
97 | #ifdef __cpp_deduction_guides |
98 | QScopeGuard fromLambda([] { }); |
99 | QScopeGuard fromFunction(func); |
100 | QScopeGuard fromFunctionPointer(&func); |
101 | QScopeGuard fromNonVoidFunction(intFunc); |
102 | QScopeGuard fromNoDiscardFunction(noDiscardFunc); |
103 | QScopeGuard fromStdFunction{std::function<void()>(func)}; |
104 | std::function<void()> stdFunction(func); |
105 | QScopeGuard fromNamedStdFunction(stdFunction); |
106 | #else |
107 | QSKIP("This test requires C++17 Class Template Argument Deduction support enabled in the compiler." ); |
108 | #endif |
109 | } |
110 | |
111 | void tst_QScopeGuard::constructionFromLvalue() |
112 | { |
113 | #ifdef __cpp_deduction_guides |
114 | Callable::resetCounts(); |
115 | { |
116 | Callable callable; |
117 | QScopeGuard guard(callable); |
118 | } |
119 | QCOMPARE(Callable::copied, 1); |
120 | QCOMPARE(Callable::moved, 0); |
121 | Callable::resetCounts(); |
122 | { |
123 | Callable callable; |
124 | auto guard = qScopeGuard(f&: callable); |
125 | } |
126 | QCOMPARE(Callable::copied, 1); |
127 | QCOMPARE(Callable::moved, 0); |
128 | #else |
129 | QSKIP("This test requires C++17 Class Template Argument Deduction support enabled in the compiler." ); |
130 | #endif |
131 | } |
132 | |
133 | void tst_QScopeGuard::constructionFromRvalue() |
134 | { |
135 | #ifdef __cpp_deduction_guides |
136 | Callable::resetCounts(); |
137 | { |
138 | Callable callable; |
139 | QScopeGuard guard(std::move(callable)); |
140 | } |
141 | QCOMPARE(Callable::copied, 0); |
142 | QCOMPARE(Callable::moved, 1); |
143 | Callable::resetCounts(); |
144 | { |
145 | Callable callable; |
146 | auto guard = qScopeGuard(f: std::move(callable)); |
147 | } |
148 | QCOMPARE(Callable::copied, 0); |
149 | QCOMPARE(Callable::moved, 1); |
150 | #else |
151 | QSKIP("This test requires C++17 Class Template Argument Deduction support enabled in the compiler." ); |
152 | #endif |
153 | } |
154 | |
155 | void tst_QScopeGuard::leavingScope() |
156 | { |
157 | auto cleanup = qScopeGuard(f: [] { s_globalState++; QCOMPARE(s_globalState, 3); }); |
158 | QCOMPARE(s_globalState, 0); |
159 | |
160 | { |
161 | auto cleanup = qScopeGuard(f: [] { s_globalState++; }); |
162 | QCOMPARE(s_globalState, 0); |
163 | } |
164 | |
165 | QCOMPARE(s_globalState, 1); |
166 | s_globalState++; |
167 | } |
168 | |
169 | void tst_QScopeGuard::exceptions() |
170 | { |
171 | s_globalState = 0; |
172 | bool caught = false; |
173 | QT_TRY |
174 | { |
175 | auto cleanup = qScopeGuard(f: [] { s_globalState++; }); |
176 | QT_THROW(std::bad_alloc()); //if Qt compiled without exceptions this is noop |
177 | s_globalState = 100; |
178 | } |
179 | QT_CATCH(...) |
180 | { |
181 | caught = true; |
182 | QCOMPARE(s_globalState, 1); |
183 | } |
184 | |
185 | QVERIFY((caught && s_globalState == 1) || (!caught && s_globalState == 101)); |
186 | |
187 | } |
188 | |
189 | QTEST_MAIN(tst_QScopeGuard) |
190 | #include "tst_qscopeguard.moc" |
191 | |