qt5base-lts/tests/auto/qpointer/tst_qpointer.cpp
Qt by Nokia 38be0d1383 Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you
want to look at revision history older than this, please refer to the
Qt Git wiki for how to use Git history grafting. At the time of
writing, this wiki is located here:

http://qt.gitorious.org/qt/pages/GitIntroductionWithQt

If you have already performed the grafting and you don't see any
history beyond this commit, try running "git log" with the "--follow"
argument.

Branched from the monolithic repo, Qt master branch, at commit
896db169ea224deb96c59ce8af800d019de63f12
2011-04-27 12:05:43 +02:00

344 lines
8.2 KiB
C++

/****************************************************************************
**
** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QPointer>
#include <QWidget>
class tst_QPointer : public QObject
{
Q_OBJECT
public:
inline tst_QPointer *me() const
{ return const_cast<tst_QPointer *>(this); }
private slots:
void constructors();
void destructor();
void assignment_operators();
void equality_operators();
void isNull();
void dereference_operators();
void disconnect();
void castDuringDestruction();
void threadSafety();
};
void tst_QPointer::constructors()
{
QPointer<QObject> p1;
QPointer<QObject> p2(this);
QPointer<QObject> p3(p2);
QCOMPARE(p1, QPointer<QObject>(0));
QCOMPARE(p2, QPointer<QObject>(this));
QCOMPARE(p3, QPointer<QObject>(this));
}
void tst_QPointer::destructor()
{
// Make two QPointer's to the same object
QObject *object = new QObject;
QPointer<QObject> p1 = object;
QPointer<QObject> p2 = object;
// Check that they point to the correct object
QCOMPARE(p1, QPointer<QObject>(object));
QCOMPARE(p2, QPointer<QObject>(object));
QCOMPARE(p1, p2);
// Destroy the guarded object
delete object;
// Check that both pointers were zeroed
QCOMPARE(p1, QPointer<QObject>(0));
QCOMPARE(p2, QPointer<QObject>(0));
QCOMPARE(p1, p2);
}
void tst_QPointer::assignment_operators()
{
QPointer<QObject> p1;
QPointer<QObject> p2;
// Test assignment with a QObject-derived object pointer
p1 = this;
p2 = p1;
QCOMPARE(p1, QPointer<QObject>(this));
QCOMPARE(p2, QPointer<QObject>(this));
QCOMPARE(p1, QPointer<QObject>(p2));
// Test assignment with a null pointer
p1 = 0;
p2 = p1;
QCOMPARE(p1, QPointer<QObject>(0));
QCOMPARE(p2, QPointer<QObject>(0));
QCOMPARE(p1, QPointer<QObject>(p2));
// Test assignment with a real QObject pointer
QObject *object = new QObject;
p1 = object;
p2 = p1;
QCOMPARE(p1, QPointer<QObject>(object));
QCOMPARE(p2, QPointer<QObject>(object));
QCOMPARE(p1, QPointer<QObject>(p2));
// Test assignment with the same pointer that's already guarded
p1 = object;
p2 = p1;
QCOMPARE(p1, QPointer<QObject>(object));
QCOMPARE(p2, QPointer<QObject>(object));
QCOMPARE(p1, QPointer<QObject>(p2));
// Cleanup
delete object;
}
void tst_QPointer::equality_operators()
{
QPointer<QObject> p1;
QPointer<QObject> p2;
QVERIFY(p1 == p2);
QObject *object = 0;
QWidget *widget = 0;
p1 = object;
QVERIFY(p1 == p2);
QVERIFY(p1 == object);
p2 = object;
QVERIFY(p2 == p1);
QVERIFY(p2 == object);
p1 = this;
QVERIFY(p1 != p2);
p2 = p1;
QVERIFY(p1 == p2);
// compare to zero
p1 = 0;
QVERIFY(p1 == 0);
QVERIFY(0 == p1);
QVERIFY(p2 != 0);
QVERIFY(0 != p2);
QVERIFY(p1 == object);
QVERIFY(object == p1);
QVERIFY(p2 != object);
QVERIFY(object != p2);
QVERIFY(p1 == widget);
QVERIFY(widget == p1);
QVERIFY(p2 != widget);
QVERIFY(widget != p2);
}
void tst_QPointer::isNull()
{
QPointer<QObject> p1;
QVERIFY(p1.isNull());
p1 = this;
QVERIFY(!p1.isNull());
p1 = 0;
QVERIFY(p1.isNull());
}
void tst_QPointer::dereference_operators()
{
QPointer<tst_QPointer> p1 = this;
QPointer<tst_QPointer> p2;
// operator->() -- only makes sense if not null
QObject *object = p1->me();
QCOMPARE(object, this);
// operator*() -- only makes sense if not null
QObject &ref = *p1;
QCOMPARE(&ref, this);
// operator T*()
QCOMPARE(static_cast<QObject *>(p1), this);
QCOMPARE(static_cast<QObject *>(p2), static_cast<QObject *>(0));
// data()
QCOMPARE(p1.data(), this);
QCOMPARE(p2.data(), static_cast<QObject *>(0));
}
void tst_QPointer::disconnect()
{
// Verify that pointer remains guarded when all signals are disconencted.
QPointer<QObject> p1 = new QObject;
QVERIFY(!p1.isNull());
p1->disconnect();
QVERIFY(!p1.isNull());
delete static_cast<QObject *>(p1);
QVERIFY(p1.isNull());
}
class ChildObject : public QObject
{
QPointer<QObject> guardedPointer;
public:
ChildObject(QObject *parent)
: QObject(parent), guardedPointer(parent)
{ }
~ChildObject();
};
ChildObject::~ChildObject()
{
QCOMPARE(static_cast<QObject *>(guardedPointer), static_cast<QObject *>(0));
QCOMPARE(qobject_cast<QObject *>(guardedPointer), static_cast<QObject *>(0));
}
class ChildWidget : public QWidget
{
QPointer<QWidget> guardedPointer;
public:
ChildWidget(QWidget *parent)
: QWidget(parent), guardedPointer(parent)
{ }
~ChildWidget();
};
ChildWidget::~ChildWidget()
{
QCOMPARE(static_cast<QWidget *>(guardedPointer), static_cast<QWidget *>(0));
QCOMPARE(qobject_cast<QWidget *>(guardedPointer), static_cast<QWidget *>(0));
}
class DerivedChild;
class DerivedParent : public QObject
{
Q_OBJECT
DerivedChild *derivedChild;
public:
DerivedParent();
~DerivedParent();
};
class DerivedChild : public QObject
{
Q_OBJECT
DerivedParent *parentPointer;
QPointer<DerivedParent> guardedParentPointer;
public:
DerivedChild(DerivedParent *parent)
: QObject(parent), parentPointer(parent), guardedParentPointer(parent)
{ }
~DerivedChild();
};
DerivedParent::DerivedParent()
: QObject()
{
derivedChild = new DerivedChild(this);
}
DerivedParent::~DerivedParent()
{
delete derivedChild;
}
DerivedChild::~DerivedChild()
{
QCOMPARE(static_cast<DerivedParent *>(guardedParentPointer), parentPointer);
QCOMPARE(qobject_cast<DerivedParent *>(guardedParentPointer), parentPointer);
}
void tst_QPointer::castDuringDestruction()
{
{
QObject *parentObject = new QObject();
(void) new ChildObject(parentObject);
delete parentObject;
}
{
QWidget *parentWidget = new QWidget();
(void) new ChildWidget(parentWidget);
delete parentWidget;
}
{
delete new DerivedParent();
}
}
class TestRunnable : public QObject, public QRunnable {
void run() {
QPointer<QObject> obj1 = new QObject;
QPointer<QObject> obj2 = new QObject;
obj1->moveToThread(thread()); // this is the owner thread
obj1->deleteLater(); // the delete will happen in the owner thread
obj2->moveToThread(thread()); // this is the owner thread
obj2->deleteLater(); // the delete will happen in the owner thread
}
};
void tst_QPointer::threadSafety()
{
QThread owner;
owner.start();
QThreadPool pool;
for (int i = 0; i < 300; i++) {
QPointer<TestRunnable> task = new TestRunnable;
task->setAutoDelete(true);
task->moveToThread(&owner);
pool.start(task);
}
pool.waitForDone();
owner.quit();
owner.wait();
}
QTEST_MAIN(tst_QPointer)
#include "tst_qpointer.moc"