1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <QtCore/QCoreApplication>
30#include <QtTest/QtTest>
31#include <private/qtestlog_p.h>
32
33class tst_Signaldumper : public QObject
34{
35 Q_OBJECT
36
37 void addConnectionTypeData();
38
39private slots:
40 void noConnections();
41 void oneSlot_data();
42 void oneSlot();
43 void oneSlotOldSyntax_data();
44 void oneSlotOldSyntax();
45 void twoSlots_data();
46 void twoSlots();
47 void twoSlotsOldSyntax_data();
48 void twoSlotsOldSyntax();
49 void signalForwarding_data();
50 void signalForwarding();
51 void signalForwardingOldSyntax_data();
52 void signalForwardingOldSyntax();
53 void slotEmittingSignal_data();
54 void slotEmittingSignal();
55 void slotEmittingSignalOldSyntax_data();
56 void slotEmittingSignalOldSyntax();
57
58 void variousTypes();
59
60 void deletingSender();
61};
62
63void tst_Signaldumper::addConnectionTypeData()
64{
65 QTest::addColumn<Qt::ConnectionType>(name: "connectionType");
66 QTest::newRow(dataTag: "direct") << Qt::ConnectionType::DirectConnection;
67 QTest::newRow(dataTag: "queued") << Qt::ConnectionType::QueuedConnection;
68}
69
70/*
71 Simple class to keep the slots and signals separate from the test
72*/
73class SignalSlotClass : public QObject
74{
75 Q_OBJECT
76
77public:
78 SignalSlotClass();
79
80public slots:
81 void slotWithoutParameters() {}
82 void slotWithParameters(int i, char c) { Q_UNUSED(i); Q_UNUSED(c); }
83 void emitSecondSignal() { emit nestedSignal(); }
84
85signals:
86 void signalWithoutParameters();
87 void signalWithParameters(int i, char c);
88
89 void nestedSignal();
90 void nestedSignalWithParameters(int i, char c);
91
92 // For the "variousTypes" test
93 void qStringSignal(QString string);
94 void qStringRefSignal(QString &string);
95 void qStringConstRefSignal(const QString &string);
96 void qByteArraySignal(QByteArray byteArray);
97 void qListSignal(QList<int> list);
98 void qVectorSignal(QVector<int> vector);
99 void qVectorRefSignal(QVector<int> &vector);
100 void qVectorConstRefSignal(const QVector<int> &vector);
101 void qVectorConstPointerSignal(const QVector<int> *vector);
102 void qVectorPointerConstSignal(QVector<int> *const vector);
103 void qVariantSignal(QVariant variant);
104};
105
106SignalSlotClass::SignalSlotClass()
107{
108 // For printing signal argument in "variousTypes" test
109 qRegisterMetaType<QVector<int>>();
110 qRegisterMetaType<QList<int>>();
111}
112
113void tst_Signaldumper::noConnections()
114{
115 SignalSlotClass signalSlotOwner;
116
117 emit signalSlotOwner.signalWithoutParameters();
118 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
119}
120
121void tst_Signaldumper::oneSlot_data()
122{
123 addConnectionTypeData();
124}
125
126void tst_Signaldumper::oneSlot()
127{
128 QFETCH(Qt::ConnectionType, connectionType);
129
130 SignalSlotClass signalSlotOwner;
131 // parameterless to parameterless
132 auto connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithoutParameters,
133 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithoutParameters, type: connectionType);
134 emit signalSlotOwner.signalWithoutParameters();
135
136 QCoreApplication::processEvents();
137 disconnect(connection);
138
139 // parameters to parameters
140 connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
141 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithParameters, type: connectionType);
142 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
143
144 QCoreApplication::processEvents();
145 disconnect(connection);
146
147 // parameters to no parameters
148 connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
149 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithoutParameters, type: connectionType);
150 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
151
152 QCoreApplication::processEvents();
153 disconnect(connection);
154}
155
156void tst_Signaldumper::oneSlotOldSyntax_data()
157{
158 addConnectionTypeData();
159}
160
161void tst_Signaldumper::oneSlotOldSyntax()
162{
163 QFETCH(Qt::ConnectionType, connectionType);
164
165 SignalSlotClass signalSlotOwner;
166 // parameterless to parameterless
167 auto connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithoutParameters()),
168 receiver: &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
169 emit signalSlotOwner.signalWithoutParameters();
170
171 QCoreApplication::processEvents();
172 disconnect(connection);
173
174 // parameters to parameters
175 connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
176 receiver: &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
177 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
178
179 QCoreApplication::processEvents();
180 disconnect(connection);
181
182 // parameters to no parameters
183 connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
184 receiver: &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
185 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
186
187 QCoreApplication::processEvents();
188 disconnect(connection);
189}
190
191void tst_Signaldumper::twoSlots_data()
192{
193 addConnectionTypeData();
194}
195
196void tst_Signaldumper::twoSlots()
197{
198 QFETCH(Qt::ConnectionType, connectionType);
199
200 // Now, instead of creating two slots or two objects, we will just do the same connection twice.
201 // The same slot will then be invoked twice.
202
203 SignalSlotClass signalSlotOwner;
204 // parameterless to parameterless
205 auto connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithoutParameters,
206 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithoutParameters, type: connectionType);
207 auto connection2 = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithoutParameters,
208 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithoutParameters, type: connectionType);
209 emit signalSlotOwner.signalWithoutParameters();
210
211 QCoreApplication::processEvents();
212 disconnect(connection);
213 disconnect(connection2);
214
215 // parameters to parameters
216 connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
217 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithParameters, type: connectionType);
218 connection2 = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
219 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithParameters, type: connectionType);
220 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
221
222 QCoreApplication::processEvents();
223 disconnect(connection);
224 disconnect(connection2);
225
226 // parameters to no parameters
227 connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
228 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithoutParameters, type: connectionType);
229 connection2 = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
230 receiver: &signalSlotOwner, slot: &SignalSlotClass::slotWithoutParameters, type: connectionType);
231 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
232
233 QCoreApplication::processEvents();
234 disconnect(connection);
235 disconnect(connection2);
236}
237
238void tst_Signaldumper::twoSlotsOldSyntax_data()
239{
240 addConnectionTypeData();
241}
242
243void tst_Signaldumper::twoSlotsOldSyntax()
244{
245 QFETCH(Qt::ConnectionType, connectionType);
246
247 // Now, instead of creating two slots or two objects, we will just do the same connection twice.
248 // The same slot will then be invoked twice.
249
250 SignalSlotClass signalSlotOwner;
251 // parameterless to parameterless
252 auto connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithoutParameters()),
253 receiver: &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
254 auto connection2 = connect(sender: &signalSlotOwner, SIGNAL(signalWithoutParameters()),
255 receiver: &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
256 emit signalSlotOwner.signalWithoutParameters();
257
258 QCoreApplication::processEvents();
259 disconnect(connection);
260 disconnect(connection2);
261
262 // parameters to parameters
263 connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
264 receiver: &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
265 connection2 = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
266 receiver: &signalSlotOwner, SLOT(slotWithParameters(int, char)), connectionType);
267 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
268
269 QCoreApplication::processEvents();
270 disconnect(connection);
271 disconnect(connection2);
272
273 // parameters to no parameters
274 connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
275 receiver: &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
276 connection2 = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
277 receiver: &signalSlotOwner, SLOT(slotWithoutParameters()), connectionType);
278 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
279
280 QCoreApplication::processEvents();
281 disconnect(connection);
282 disconnect(connection2);
283}
284
285void tst_Signaldumper::signalForwarding_data()
286{
287 addConnectionTypeData();
288}
289
290void tst_Signaldumper::signalForwarding()
291{
292 QFETCH(Qt::ConnectionType, connectionType);
293
294 SignalSlotClass signalSlotOwner;
295
296 // parameterless signal to parameterless signal
297 auto connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithoutParameters,
298 receiver: &signalSlotOwner, slot: &SignalSlotClass::nestedSignal, type: connectionType);
299 emit signalSlotOwner.signalWithoutParameters();
300
301 QCoreApplication::processEvents();
302 disconnect(connection);
303
304 // parameter(full) signal to parameter(full) signal
305 connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
306 receiver: &signalSlotOwner, slot: &SignalSlotClass::nestedSignalWithParameters, type: connectionType);
307 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
308
309 QCoreApplication::processEvents();
310 disconnect(connection);
311
312 // parameter(full) signal to parameterless signal
313 connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithParameters,
314 receiver: &signalSlotOwner, slot: &SignalSlotClass::nestedSignal, type: connectionType);
315 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
316
317 QCoreApplication::processEvents();
318 disconnect(connection);
319}
320
321void tst_Signaldumper::signalForwardingOldSyntax_data()
322{
323 addConnectionTypeData();
324}
325
326void tst_Signaldumper::signalForwardingOldSyntax()
327{
328 QFETCH(Qt::ConnectionType, connectionType);
329
330 SignalSlotClass signalSlotOwner;
331
332 // parameterless signal to parameterless signal
333 auto connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithoutParameters()),
334 receiver: &signalSlotOwner, SIGNAL(nestedSignal()), connectionType);
335 emit signalSlotOwner.signalWithoutParameters();
336
337 QCoreApplication::processEvents();
338 disconnect(connection);
339
340 // parameter(full) signal to parameter(full) signal
341 connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
342 receiver: &signalSlotOwner, SIGNAL(nestedSignalWithParameters(int, char)), connectionType);
343 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
344
345 QCoreApplication::processEvents();
346 disconnect(connection);
347
348 // parameter(full) signal to parameterless signal
349 connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithParameters(int, char)),
350 receiver: &signalSlotOwner, SIGNAL(nestedSignal()), connectionType);
351 emit signalSlotOwner.signalWithParameters(i: 242, c: 'm');
352
353 QCoreApplication::processEvents();
354 disconnect(connection);
355}
356
357void tst_Signaldumper::slotEmittingSignal_data()
358{
359 addConnectionTypeData();
360}
361
362void tst_Signaldumper::slotEmittingSignal()
363{
364 QFETCH(Qt::ConnectionType, connectionType);
365
366 SignalSlotClass signalSlotOwner;
367
368 auto connection = connect(sender: &signalSlotOwner, signal: &SignalSlotClass::signalWithoutParameters,
369 receiver: &signalSlotOwner, slot: &SignalSlotClass::emitSecondSignal, type: connectionType);
370 emit signalSlotOwner.signalWithoutParameters();
371 QCoreApplication::processEvents();
372 disconnect(connection);
373}
374
375void tst_Signaldumper::slotEmittingSignalOldSyntax_data()
376{
377 addConnectionTypeData();
378}
379
380void tst_Signaldumper::slotEmittingSignalOldSyntax()
381{
382 QFETCH(Qt::ConnectionType, connectionType);
383
384 SignalSlotClass signalSlotOwner;
385
386 auto connection = connect(sender: &signalSlotOwner, SIGNAL(signalWithoutParameters()),
387 receiver: &signalSlotOwner, SLOT(emitSecondSignal()), connectionType);
388 emit signalSlotOwner.signalWithoutParameters();
389 QCoreApplication::processEvents();
390 disconnect(connection);
391}
392
393void tst_Signaldumper::variousTypes()
394{
395 SignalSlotClass signalSlotOwner;
396 QString string = QString::fromLatin1(str: "Test string");
397 emit signalSlotOwner.qStringSignal(string);
398 emit signalSlotOwner.qStringRefSignal(string);
399 emit signalSlotOwner.qStringConstRefSignal(string);
400 emit signalSlotOwner.qByteArraySignal(byteArray: QByteArray("Test bytearray"));
401
402 QList<int> list{1, 2, 3, 242};
403 emit signalSlotOwner.qListSignal(list);
404
405 QVector<int> vector{1, 2, 3, 242};
406 emit signalSlotOwner.qVectorSignal(vector);
407 emit signalSlotOwner.qVectorRefSignal(vector);
408 emit signalSlotOwner.qVectorConstRefSignal(vector);
409 emit signalSlotOwner.qVectorConstPointerSignal(vector: &vector);
410 emit signalSlotOwner.qVectorPointerConstSignal(vector: &vector);
411
412 QVariant variant = 24;
413 emit signalSlotOwner.qVariantSignal(variant);
414 variant = QVariant(string);
415 emit signalSlotOwner.qVariantSignal(variant);
416}
417
418void tst_Signaldumper::deletingSender()
419{
420 SignalSlotClass *signalSlotOwner = new SignalSlotClass();
421 connect(sender: signalSlotOwner, signal: &SignalSlotClass::signalWithoutParameters, slot: [signalSlotOwner]() {
422 delete signalSlotOwner;
423 });
424 emit signalSlotOwner->signalWithoutParameters();
425}
426
427int main(int argc, char *argv[])
428{
429 std::vector<const char*> args(argv, argv + argc);
430 args.push_back(x: "-vs");
431 argc = args.size();
432 argv = const_cast<char**>(&args[0]);
433
434 QTEST_MAIN_IMPL(tst_Signaldumper)
435}
436
437#include "tst_signaldumper.moc"
438

source code of qtbase/tests/auto/testlib/selftests/signaldumper/tst_signaldumper.cpp