summaryrefslogtreecommitdiffstats
path: root/tests/auto/qsharedpointer
diff options
context:
space:
mode:
authoraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
committeraxis <qt-info@nokia.com>2009-04-24 11:34:15 (GMT)
commit8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76 (patch)
treea17e1a767a89542ab59907462206d7dcf2e504b2 /tests/auto/qsharedpointer
downloadQt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.zip
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.gz
Qt-8f427b2b914d5b575a4a7c0ed65d2fb8f45acc76.tar.bz2
Long live Qt for S60!
Diffstat (limited to 'tests/auto/qsharedpointer')
-rw-r--r--tests/auto/qsharedpointer/.gitignore1
-rw-r--r--tests/auto/qsharedpointer/externaltests.cpp678
-rw-r--r--tests/auto/qsharedpointer/externaltests.h132
-rw-r--r--tests/auto/qsharedpointer/externaltests.pri7
-rw-r--r--tests/auto/qsharedpointer/qsharedpointer.pro7
-rw-r--r--tests/auto/qsharedpointer/tst_qsharedpointer.cpp919
6 files changed, 1744 insertions, 0 deletions
diff --git a/tests/auto/qsharedpointer/.gitignore b/tests/auto/qsharedpointer/.gitignore
new file mode 100644
index 0000000..3cd9f1a
--- /dev/null
+++ b/tests/auto/qsharedpointer/.gitignore
@@ -0,0 +1 @@
+tst_qsharedpointer
diff --git a/tests/auto/qsharedpointer/externaltests.cpp b/tests/auto/qsharedpointer/externaltests.cpp
new file mode 100644
index 0000000..1e9629e
--- /dev/null
+++ b/tests/auto/qsharedpointer/externaltests.cpp
@@ -0,0 +1,678 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "externaltests.h"
+
+#include <QtCore/QTemporaryFile>
+#include <QtCore/QProcess>
+#include <QtCore/QByteArray>
+#include <QtCore/QString>
+#include <QtCore/QFileInfo>
+#include <QtCore/QDir>
+#include <QtCore/QDirIterator>
+#include <QtCore/QDateTime>
+
+#ifdef Q_OS_SYMBIAN
+#define DEFAULT_MAKESPEC "X:/STLsupport/mkspecs/symbian-abld/"
+#endif
+
+#ifndef DEFAULT_MAKESPEC
+# error DEFAULT_MAKESPEC not defined
+#endif
+
+static QString makespec()
+{
+ static const char default_makespec[] = DEFAULT_MAKESPEC;
+ const char *p;
+ for (p = default_makespec + sizeof(default_makespec); p >= default_makespec; --p)
+ if (*p == '/' || *p == '\\')
+ break;
+
+ return QString::fromLatin1(p + 1);
+}
+
+static bool removeRecursive(const QString &pathname)
+{
+ QFileInfo fi(pathname);
+ if (!fi.exists())
+ return true;
+
+ if (fi.isFile())
+ return QFile::remove(pathname);
+
+ if (!fi.isDir()) {
+ // not a file or directory. How do I remove it?
+ return false;
+ }
+
+ // not empty -- we must empty it first
+ QDirIterator di(pathname, QDir::AllEntries | QDir::Hidden | QDir::System | QDir::NoDotAndDotDot);
+ while (di.hasNext()) {
+ di.next();
+ if (!di.fileInfo().exists() && !di.fileInfo().isSymLink())
+ continue;
+ bool ok;
+ if (di.fileInfo().isFile() || di.fileInfo().isSymLink())
+ ok = QFile::remove(di.filePath());
+ else
+ ok = removeRecursive(di.filePath());
+ if (!ok) {
+ return false;
+ }
+ }
+
+ QDir dir(pathname);
+ QString dirname = dir.dirName();
+ dir.cdUp();
+ return dir.rmdir(dirname);
+}
+
+QT_BEGIN_NAMESPACE
+namespace QTest {
+ class QExternalTestPrivate
+ {
+ public:
+ QExternalTestPrivate()
+ : qtModules(QExternalTest::QtCore | QExternalTest::QtGui | QExternalTest::QtTest),
+ appType(QExternalTest::AutoApplication),
+ debugMode(true),
+ exitCode(-1)
+ {
+ }
+ ~QExternalTestPrivate()
+ {
+ clear();
+ }
+
+ enum Target { Compile, Link, Run };
+
+ QList<QByteArray> qmakeLines;
+ QByteArray programHeader;
+ QExternalTest::QtModules qtModules;
+ QExternalTest::ApplicationType appType;
+ bool debugMode;
+
+ QString temporaryDir;
+ QByteArray sourceCode;
+ QByteArray std_out;
+ QByteArray std_err;
+ int exitCode;
+ QExternalTest::Stage failedStage;
+
+ void clear();
+ bool tryCompile(const QByteArray &body);
+ bool tryLink(const QByteArray &body);
+ bool tryRun(const QByteArray &body);
+
+ private:
+ void removeTemporaryDirectory();
+ bool createTemporaryDirectory();
+ bool prepareSourceCode(const QByteArray &body);
+ bool createProjectFile();
+ bool runQmake();
+ bool runMake(Target target);
+ bool commonSetup(const QByteArray &body);
+ };
+
+ QExternalTest::QExternalTest()
+ : d(new QExternalTestPrivate)
+ {
+ }
+
+ QExternalTest::~QExternalTest()
+ {
+ delete d;
+ }
+
+ bool QExternalTest::isDebugMode() const
+ {
+ return d->debugMode;
+ }
+
+ void QExternalTest::setDebugMode(bool enable)
+ {
+ d->debugMode = enable;
+ }
+
+ QList<QByteArray> QExternalTest::qmakeSettings() const
+ {
+ return d->qmakeLines;
+ }
+
+ void QExternalTest::setQmakeSettings(const QList<QByteArray> &settings)
+ {
+ d->qmakeLines = settings;
+ }
+
+ QExternalTest::QtModules QExternalTest::qtModules() const
+ {
+ return d->qtModules;
+ }
+
+ void QExternalTest::setQtModules(QtModules modules)
+ {
+ d->qtModules = modules;
+ }
+
+ QExternalTest::ApplicationType QExternalTest::applicationType() const
+ {
+ return d->appType;
+ }
+
+ void QExternalTest::setApplicationType(ApplicationType type)
+ {
+ d->appType = type;
+ }
+
+ QByteArray QExternalTest::programHeader() const
+ {
+ return d->programHeader;
+ }
+
+ void QExternalTest::setProgramHeader(const QByteArray &header)
+ {
+ d->programHeader = header;
+ }
+
+ bool QExternalTest::tryCompile(const QByteArray &body)
+ {
+ return d->tryCompile(body) && d->exitCode == 0;
+ }
+
+ bool QExternalTest::tryLink(const QByteArray &body)
+ {
+ return d->tryLink(body) && d->exitCode == 0;
+ }
+
+ bool QExternalTest::tryRun(const QByteArray &body)
+ {
+ return d->tryRun(body) && d->exitCode == 0;
+ }
+
+ bool QExternalTest::tryCompileFail(const QByteArray &body)
+ {
+ return d->tryCompile(body) && d->exitCode != 0;
+ }
+
+ bool QExternalTest::tryLinkFail(const QByteArray &body)
+ {
+ return d->tryLink(body) && d->exitCode != 0;
+ }
+
+ bool QExternalTest::tryRunFail(const QByteArray &body)
+ {
+ return d->tryRun(body) && d->exitCode != 0;
+ }
+
+ QExternalTest::Stage QExternalTest::failedStage() const
+ {
+ return d->failedStage;
+ }
+
+ int QExternalTest::exitCode() const
+ {
+ return d->exitCode;
+ }
+
+ QByteArray QExternalTest::fullProgramSource() const
+ {
+ return d->sourceCode;
+ }
+
+ QByteArray QExternalTest::standardOutput() const
+ {
+ return d->std_out;
+ }
+
+ QByteArray QExternalTest::standardError() const
+ {
+ return d->std_err;
+ }
+
+ QString QExternalTest::errorReport() const
+ {
+ const char *stage = 0;
+ switch (d->failedStage) {
+ case FileStage:
+ stage = "creating files";
+ break;
+ case QmakeStage:
+ stage = "executing qmake";
+ break;
+ case CompilationStage:
+ stage = "during compilation";
+ break;
+ case LinkStage:
+ stage = "during linking";
+ break;
+ case RunStage:
+ stage = "executing program";
+ break;
+ }
+
+ QString report = QString::fromLatin1(
+ "External test failed %1 with exit code %4\n"
+ "==== standard error: ====\n"
+ "%2\n"
+ "==== standard output: ====\n"
+ "%3\n"
+ "==== ====\n");
+ return report.arg(QString::fromLatin1(stage),
+ QString::fromLocal8Bit(d->std_err),
+ QString::fromLocal8Bit(d->std_out))
+ .arg(d->exitCode);
+ }
+
+ // actual execution code
+ void QExternalTestPrivate::clear()
+ {
+ if (!temporaryDir.isEmpty())
+ removeTemporaryDirectory();
+
+ sourceCode.clear();
+ std_out.clear();
+ std_err.clear();
+ exitCode = -1;
+ failedStage = QExternalTest::FileStage;
+ }
+
+ void QExternalTestPrivate::removeTemporaryDirectory()
+ {
+ Q_ASSERT(!temporaryDir.isEmpty());
+ removeRecursive(temporaryDir);
+ temporaryDir.clear();
+ }
+
+ bool QExternalTestPrivate::prepareSourceCode(const QByteArray &body)
+ {
+ sourceCode.clear();
+ sourceCode.reserve(8192);
+
+ // Add Qt header includes
+ if (qtModules & QExternalTest::QtCore)
+ sourceCode += "#include <QtCore/QtCore>\n";
+ if (qtModules & QExternalTest::QtGui)
+ sourceCode += "#include <QtGui/QtGui>\n";
+ if (qtModules & QExternalTest::QtNetwork)
+ sourceCode += "#include <QtNetwork/QtNetwork>\n";
+ if (qtModules & QExternalTest::QtXml)
+ sourceCode += "#include <QtXml/QtXml>\n";
+ if (qtModules & QExternalTest::QtXmlPatterns)
+ sourceCode += "#include <QtXmlPatterns/QtXmlPatterns>\n";
+ if (qtModules & QExternalTest::QtOpenGL)
+ sourceCode += "#include <QtOpenGL/QtOpenGL>\n";
+ if (qtModules & QExternalTest::QtSql)
+ sourceCode += "#include <QtSql/QtSql>\n";
+ if (qtModules & QExternalTest::Qt3Support)
+ sourceCode += "#include <Qt3Support/Qt3Support>\n";
+ if (qtModules & QExternalTest::QtSvg)
+ sourceCode += "#include <QtSvg/QtSvg>\n";
+ if (qtModules & QExternalTest::QtScript)
+ sourceCode += "#include <QtScript/QtScript>\n";
+ if (qtModules & QExternalTest::QtTest)
+ sourceCode += "#include <QtTest/QtTest>\n";
+ if (qtModules & QExternalTest::QtDBus)
+ sourceCode += "#include <QtDBus/QtDBus>\n";
+ if (qtModules & QExternalTest::QtWebKit)
+ sourceCode += "#include <QtWebKit/QtWebKit>\n";
+ if (qtModules & QExternalTest::Phonon)
+ sourceCode += "#include <Phonon/Phonon>\n";
+ sourceCode +=
+ "#include <stdlib.h>\n"
+ "#include <stddef.h>\n";
+
+ sourceCode += programHeader;
+
+ sourceCode +=
+ "\n"
+ "void q_external_test_user_code()\n"
+ "{\n"
+ " // HERE STARTS THE USER CODE\n";
+ sourceCode += body;
+ sourceCode +=
+ "\n"
+ " // HERE ENDS THE USER CODE\n"
+ "}\n"
+ "\n"
+ "#ifdef Q_OS_WIN\n"
+ "#include <windows.h>\n"
+ "static void q_test_setup()\n"
+ "{\n"
+ " SetErrorMode(SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX | SEM_NOOPENFILEERRORBOX);\n"
+ "}\n"
+ "#else\n"
+ "static void q_test_setup() { }\n"
+ "#endif\n"
+ "int main(int argc, char **argv)\n"
+ "{\n";
+
+ switch (appType) {
+ applicationless:
+ case QExternalTest::Applicationless:
+ sourceCode +=
+ " (void)argc; (void)argv;\n";
+ break;
+
+ coreapplication:
+ case QExternalTest::QCoreApplication:
+ sourceCode +=
+ " QCoreApplication app(argc, argv);\n";
+ break;
+
+ case QExternalTest::QApplicationTty:
+ sourceCode +=
+ " QApplication app(argc, argv, QApplication::Tty);\n";
+ break;
+
+ guiapplication:
+ case QExternalTest::QApplicationGuiClient:
+ sourceCode +=
+ " QApplication app(argc, argv, QApplication::GuiClient);\n";
+ break;
+
+ case QExternalTest::QApplicationGuiServer:
+ sourceCode +=
+ " QApplication app(argc, argv, QApplication::GuiServer);\n";
+ break;
+
+ case QExternalTest::AutoApplication:
+ if (qtModules & QExternalTest::QtGui)
+ goto guiapplication;
+ if (qtModules == 0)
+ goto applicationless;
+ goto coreapplication;
+ }
+
+ sourceCode +=
+ " q_test_setup();\n"
+ " q_external_test_user_code();\n"
+ " return 0;\n"
+ "}\n";
+
+ QFile sourceFile(temporaryDir + QLatin1String("/project.cpp"));
+ if (!sourceFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ std_err = sourceFile.errorString().toLocal8Bit();
+ return false;
+ }
+
+ sourceFile.write(sourceCode);
+ return true;
+ }
+
+ bool QExternalTestPrivate::createTemporaryDirectory()
+ {
+ QDir temp = QDir::temp();
+ QString subdir = QString::fromLatin1("qexternaltest-%1-%2-%3")
+ .arg(QDateTime::currentDateTime().toString(QLatin1String("yyyyMMddhhmmss")))
+ .arg(quintptr(this), 0, 16)
+ .arg(qrand());
+ if (!temp.mkdir(subdir))
+ return false;
+
+ if (!temp.cd(subdir))
+ return false;
+
+ temporaryDir = temp.absolutePath();
+ return true;
+ }
+
+ bool QExternalTestPrivate::createProjectFile()
+ {
+ Q_ASSERT(!temporaryDir.isEmpty());
+
+ QFile projectFile(temporaryDir + QLatin1String("/project.pro"));
+ if (!projectFile.open(QIODevice::WriteOnly | QIODevice::Truncate | QIODevice::Text)) {
+ std_err = projectFile.errorString().toLocal8Bit();
+ return false;
+ }
+
+ projectFile.write(
+ "TEMPLATE = app\n"
+ "\n"
+ "TARGET = externaltest\n"
+ "CONFIG -= app_bundle\n" // for the Mac
+ "CONFIG -= debug_and_release\n"
+ "DESTDIR = .\n"
+ "OBJECTS_DIR = .\n"
+ "UI_DIR = .\n"
+ "MOC_DIR = .\n"
+ "RCC_DIR = .\n"
+ "HEADERS +=\n"
+ "SOURCES += project.cpp\n"
+ "QT -= core gui\n"
+ "INCLUDEPATH += . ");
+ projectFile.write(QFile::encodeName(QDir::currentPath()));
+
+ if (debugMode)
+ projectFile.write("\nCONFIG += debug\n");
+ else
+ projectFile.write("\nCONFIG += release\n");
+
+ // Add Qt modules
+ if (qtModules & QExternalTest::QtCore)
+ projectFile.write("QT += core\n");
+ if (qtModules & QExternalTest::QtGui)
+ projectFile.write("QT += gui\n");
+ if (qtModules & QExternalTest::QtNetwork)
+ projectFile.write("QT += network\n");
+ if (qtModules & QExternalTest::QtXml)
+ projectFile.write("QT += xml\n");
+ if (qtModules & QExternalTest::QtXmlPatterns)
+ projectFile.write("QT += xmlpatterns\n");
+ if (qtModules & QExternalTest::QtOpenGL)
+ projectFile.write("QT += opengl\n");
+ if (qtModules & QExternalTest::QtSql)
+ projectFile.write("QT += sql\n");
+ if (qtModules & QExternalTest::Qt3Support)
+ projectFile.write("QT += qt3support\n");
+ if (qtModules & QExternalTest::QtSvg)
+ projectFile.write("QT += svg\n");
+ if (qtModules & QExternalTest::QtScript)
+ projectFile.write("QT += script\n");
+ if (qtModules & QExternalTest::QtTest)
+ projectFile.write("QT += testlib\n");
+ if (qtModules & QExternalTest::QtDBus)
+ projectFile.write("QT += dbus\n");
+ if (qtModules & QExternalTest::QtWebKit)
+ projectFile.write("QT += webkit\n");
+ if (qtModules & QExternalTest::Phonon)
+ projectFile.write("QT += phonon\n");
+
+ projectFile.write("\n### User-specified settings start ###\n");
+ foreach (QByteArray line, qmakeLines) {
+ projectFile.write(line);
+ projectFile.write("\n");
+ }
+ projectFile.write("\n### User-specified settings end ###\n");
+
+ // Use qmake to just compile:
+ projectFile.write(
+ "\n"
+ "test_compile.depends += $(OBJECTS)\n"
+ "QMAKE_EXTRA_TARGETS += test_compile\n");
+
+ // Use qmake to run the app too:
+ projectFile.write(
+ "\n"
+ "unix:test_run.commands = ./$(QMAKE_TARGET)\n"
+ "else:test_run.commands = $(QMAKE_TARGET)\n"
+ "embedded:test_run.commands += -qws\n"
+ "QMAKE_EXTRA_TARGETS += test_run\n");
+
+ return true;
+ }
+
+ bool QExternalTestPrivate::runQmake()
+ {
+ Q_ASSERT(!temporaryDir.isEmpty());
+ if (!createProjectFile())
+ return false;
+
+ failedStage = QExternalTest::QmakeStage;
+ QProcess qmake;
+ QStringList args;
+ args << QLatin1String("-makefile")
+ << QLatin1String("-spec")
+ << makespec()
+ << QLatin1String("project.pro");
+ qmake.setWorkingDirectory(temporaryDir);
+ qmake.start(QLatin1String("qmake"), args);
+
+ std_out += "### --- stdout from qmake --- ###\n";
+ std_err += "### --- stderr from qmake --- ###\n";
+ bool ok = qmake.waitForStarted();
+ if (!ok) {
+ exitCode = 255;
+ std_err += "qmake: ";
+ std_err += qmake.errorString().toLocal8Bit();
+ } else {
+ ok = qmake.waitForFinished();
+ exitCode = qmake.exitCode();
+
+ std_out += qmake.readAllStandardOutput();
+ std_err += qmake.readAllStandardError();
+ }
+
+ return ok && exitCode == 0;
+ }
+
+ bool QExternalTestPrivate::runMake(Target target)
+ {
+ Q_ASSERT(!temporaryDir.isEmpty());
+
+ QProcess make;
+ make.setWorkingDirectory(temporaryDir);
+
+ QStringList environment = QProcess::systemEnvironment();
+ environment += QLatin1String("LC_ALL=C");
+ make.setEnvironment(environment);
+
+ QStringList args;
+ if (target == Compile)
+ args << QLatin1String("test_compile");
+ else if (target == Run)
+ args << QLatin1String("test_run");
+
+#if defined(Q_OS_WIN) && !defined(Q_CC_MINGW)
+ make.start(QLatin1String("nmake.exe"), args);
+ make.waitForStarted();
+#else
+ static const char makes[] =
+# ifdef Q_CC_MINGW
+ "mingw32-make.exe\0"
+# endif
+ "gmake\0"
+ "make\0";
+ for (const char *p = makes; *p; p += strlen(p) + 1) {
+ make.start(QLatin1String(p), args);
+ if (make.waitForStarted())
+ break;
+ }
+#endif
+
+ if (make.state() != QProcess::Running) {
+ exitCode = 255;
+ std_err += "make: ";
+ std_err += make.errorString().toLocal8Bit();
+ return false;
+ }
+
+ bool ok = make.waitForFinished();
+ exitCode = make.exitCode();
+ std_out += make.readAllStandardOutput();
+ std_err += make.readAllStandardError();
+
+ return ok;
+ }
+
+ bool QExternalTestPrivate::commonSetup(const QByteArray &body)
+ {
+ clear();
+
+ if (!createTemporaryDirectory())
+ return false;
+ if (!createProjectFile())
+ return false;
+ if (!prepareSourceCode(body))
+ return false;
+ if (!runQmake())
+ return false;
+ return true;
+ }
+
+ bool QExternalTestPrivate::tryCompile(const QByteArray &body)
+ {
+ if (!commonSetup(body))
+ return false;
+
+ // compile
+ failedStage = QExternalTest::CompilationStage;
+ std_out += "\n### --- stdout from make (compilation) --- ###\n";
+ std_err += "\n### --- stderr from make (compilation) --- ###\n";
+ return runMake(Compile);
+ }
+
+ bool QExternalTestPrivate::tryLink(const QByteArray &body)
+ {
+ if (!tryCompile(body) || exitCode != 0)
+ return false;
+
+ // link
+ failedStage = QExternalTest::LinkStage;
+ std_out += "\n### --- stdout from make (linking) --- ###\n";
+ std_err += "\n### --- stderr from make (linking) --- ###\n";
+ return runMake(Link);
+ }
+
+ bool QExternalTestPrivate::tryRun(const QByteArray &body)
+ {
+ if (!tryLink(body) || exitCode != 0)
+ return false;
+
+ // run
+ failedStage = QExternalTest::RunStage;
+ std_out += "\n### --- stdout from process --- ###\n";
+ std_err += "\n### --- stderr from process --- ###\n";
+ return runMake(Run);
+ }
+}
+QT_END_NAMESPACE
diff --git a/tests/auto/qsharedpointer/externaltests.h b/tests/auto/qsharedpointer/externaltests.h
new file mode 100644
index 0000000..e92ae77
--- /dev/null
+++ b/tests/auto/qsharedpointer/externaltests.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#ifndef QTEST_EXTERNAL_TESTS_H
+#define QTEST_EXTERNAL_TESTS_H
+
+#include <QList>
+#include <QByteArray>
+
+QT_BEGIN_NAMESPACE
+namespace QTest {
+ class QExternalTestPrivate;
+ class QExternalTest
+ {
+ public:
+ QExternalTest();
+ ~QExternalTest();
+
+ enum Stage {
+ FileStage,
+ QmakeStage,
+ CompilationStage,
+ LinkStage,
+ RunStage
+ };
+
+ enum QtModule {
+ QtCore = 0x0001,
+ QtGui = 0x0002,
+ QtNetwork = 0x0004,
+ QtXml = 0x0008,
+ QtXmlPatterns=0x0010,
+ QtOpenGL = 0x0020,
+ QtSql = 0x0040,
+ Qt3Support = 0x0080,
+ QtSvg = 0x0100,
+ QtScript = 0x0200,
+ QtTest = 0x0400,
+ QtDBus = 0x0800,
+ QtWebKit = 0x1000,
+ Phonon = 0x2000 // odd man out
+ };
+ Q_DECLARE_FLAGS(QtModules, QtModule)
+
+ enum ApplicationType {
+ AutoApplication,
+ Applicationless,
+ QCoreApplication,
+ QApplicationTty,
+ QApplicationGuiClient,
+ QApplicationGuiServer
+ };
+
+ bool isDebugMode() const;
+ void setDebugMode(bool enable);
+
+ QList<QByteArray> qmakeSettings() const;
+ void setQmakeSettings(const QList<QByteArray> &settings);
+
+ QtModules qtModules() const;
+ void setQtModules(QtModules modules);
+
+ ApplicationType applicationType() const;
+ void setApplicationType(ApplicationType type);
+
+ QByteArray programHeader() const;
+ void setProgramHeader(const QByteArray &header);
+
+ // execution:
+ bool tryCompile(const QByteArray &body);
+ bool tryLink(const QByteArray &body);
+ bool tryRun(const QByteArray &body);
+ bool tryCompileFail(const QByteArray &body);
+ bool tryLinkFail(const QByteArray &body);
+ bool tryRunFail(const QByteArray &body);
+
+ Stage failedStage() const;
+ int exitCode() const;
+ QByteArray fullProgramSource() const;
+ QByteArray standardOutput() const;
+ QByteArray standardError() const;
+
+ QString errorReport() const;
+
+ private:
+ QExternalTestPrivate * const d;
+ };
+
+ Q_DECLARE_OPERATORS_FOR_FLAGS(QExternalTest::QtModules)
+}
+QT_END_NAMESPACE
+
+#endif
diff --git a/tests/auto/qsharedpointer/externaltests.pri b/tests/auto/qsharedpointer/externaltests.pri
new file mode 100644
index 0000000..0ded149
--- /dev/null
+++ b/tests/auto/qsharedpointer/externaltests.pri
@@ -0,0 +1,7 @@
+SOURCES += $$PWD/externaltests.cpp
+cleanedQMAKESPEC = $$replace(QMAKESPEC, \\\\, /)
+!symbian:DEFINES += DEFAULT_MAKESPEC=\\\"$$cleanedQMAKESPEC\\\"
+
+embedded:DEFINES += QTEST_NO_RTTI QTEST_CROSS_COMPILED
+wince*:DEFINES += QTEST_CROSS_COMPILED
+symbian: DEFINES += QTEST_CROSS_COMPILED
diff --git a/tests/auto/qsharedpointer/qsharedpointer.pro b/tests/auto/qsharedpointer/qsharedpointer.pro
new file mode 100644
index 0000000..4532260
--- /dev/null
+++ b/tests/auto/qsharedpointer/qsharedpointer.pro
@@ -0,0 +1,7 @@
+load(qttest_p4)
+
+SOURCES += tst_qsharedpointer.cpp
+QT = core
+!symbian:DEFINES += SRCDIR=\\\"$$PWD\\\"
+
+include(externaltests.pri)
diff --git a/tests/auto/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp
new file mode 100644
index 0000000..becbf52
--- /dev/null
+++ b/tests/auto/qsharedpointer/tst_qsharedpointer.cpp
@@ -0,0 +1,919 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+
+#include "qsharedpointer.h"
+#include "externaltests.h"
+#include <QtTest/QtTest>
+
+#ifdef Q_OS_SYMBIAN
+#define SRCDIR "."
+#endif
+
+class tst_QSharedPointer: public QObject
+{
+ Q_OBJECT
+
+private slots:
+ void basics_data();
+ void basics();
+ void forwardDeclaration1();
+ void forwardDeclaration2();
+ void memoryManagement();
+ void downCast();
+ void upCast();
+ void differentPointers();
+#ifndef QTEST_NO_RTTI
+ void dynamicCast();
+ void dynamicCastFailure();
+#endif
+ void customDeleter();
+ void constCorrectness();
+ void validConstructs();
+ void invalidConstructs_data();
+ void invalidConstructs();
+};
+
+class Data
+{
+public:
+ static int destructorCounter;
+ static int generationCounter;
+ int generation;
+
+ Data() : generation(++generationCounter)
+ { }
+
+ virtual ~Data()
+ {
+ Q_ASSERT_X(generation > 0, "tst_QSharedPointer", "Double deletion!");
+ generation = 0;
+ ++destructorCounter;
+ }
+
+ void doDelete()
+ {
+ delete this;
+ }
+
+ bool alsoDelete()
+ {
+ doDelete();
+ return true;
+ }
+
+ virtual void virtualDelete()
+ {
+ delete this;
+ }
+};
+int Data::generationCounter = 0;
+int Data::destructorCounter = 0;
+
+void tst_QSharedPointer::basics_data()
+{
+ QTest::addColumn<bool>("isNull");
+ QTest::newRow("null") << true;
+ QTest::newRow("non-null") << false;
+}
+
+void tst_QSharedPointer::basics()
+{
+ {
+ QSharedPointer<Data> ptr;
+ QWeakPointer<Data> weakref;
+
+ QCOMPARE(sizeof(ptr), 2*sizeof(void*));
+ QCOMPARE(sizeof(weakref), 2*sizeof(void*));
+ }
+
+ QFETCH(bool, isNull);
+ Data *aData = 0;
+ if (!isNull)
+ aData = new Data;
+ Data *otherData = new Data;
+ QSharedPointer<Data> ptr(aData);
+
+ {
+ // basic self tests
+ QCOMPARE(ptr.isNull(), isNull);
+ QCOMPARE(bool(ptr), !isNull);
+ QCOMPARE(!ptr, isNull);
+
+ QCOMPARE(ptr.data(), aData);
+ QCOMPARE(ptr.operator->(), aData);
+ Data &dataReference = *ptr;
+ QCOMPARE(&dataReference, aData);
+
+ QVERIFY(ptr == aData);
+ QVERIFY(!(ptr != aData));
+ QVERIFY(aData == ptr);
+ QVERIFY(!(aData != ptr));
+
+ QVERIFY(ptr != otherData);
+ QVERIFY(otherData != ptr);
+ QVERIFY(! (ptr == otherData));
+ QVERIFY(! (otherData == ptr));
+ }
+ QVERIFY(!ptr.d || ptr.d->weakref == 1);
+ QVERIFY(!ptr.d || ptr.d->strongref == 1);
+
+ {
+ // create another object:
+ QSharedPointer<Data> otherCopy(otherData);
+ QVERIFY(ptr != otherCopy);
+ QVERIFY(otherCopy != ptr);
+ QVERIFY(! (ptr == otherCopy));
+ QVERIFY(! (otherCopy == ptr));
+
+ // otherData is deleted here
+ }
+ QVERIFY(!ptr.d || ptr.d->weakref == 1);
+ QVERIFY(!ptr.d || ptr.d->strongref == 1);
+
+ {
+ // create a copy:
+ QSharedPointer<Data> copy(ptr);
+ QVERIFY(copy == ptr);
+ QVERIFY(ptr == copy);
+ QVERIFY(! (copy != ptr));
+ QVERIFY(! (ptr != copy));
+ QCOMPARE(copy, ptr);
+ QCOMPARE(ptr, copy);
+
+ QCOMPARE(copy.isNull(), isNull);
+ QCOMPARE(copy.data(), aData);
+ QVERIFY(copy == aData);
+ }
+ QVERIFY(!ptr.d || ptr.d->weakref == 1);
+ QVERIFY(!ptr.d || ptr.d->strongref == 1);
+
+ {
+ // create a weak reference:
+ QWeakPointer<Data> weak(ptr);
+ QCOMPARE(weak.isNull(), isNull);
+ QCOMPARE(!weak, isNull);
+ QCOMPARE(bool(weak), !isNull);
+
+ QVERIFY(ptr == weak);
+ QVERIFY(weak == ptr);
+ QVERIFY(! (ptr != weak));
+ QVERIFY(! (weak != ptr));
+
+ // create another reference:
+ QWeakPointer<Data> weak2(weak);
+ QCOMPARE(weak2.isNull(), isNull);
+ QCOMPARE(!weak2, isNull);
+ QCOMPARE(bool(weak2), !isNull);
+
+ QVERIFY(weak2 == weak);
+ QVERIFY(weak == weak2);
+ QVERIFY(! (weak2 != weak));
+ QVERIFY(! (weak != weak2));
+
+ // create a strong reference back:
+ QSharedPointer<Data> strong(weak);
+ QVERIFY(strong == weak);
+ QVERIFY(strong == ptr);
+ QCOMPARE(strong.data(), aData);
+ }
+ QVERIFY(!ptr.d || ptr.d->weakref == 1);
+ QVERIFY(!ptr.d || ptr.d->strongref == 1);
+
+ // aData is deleted here
+}
+
+class ForwardDeclared;
+void tst_QSharedPointer::forwardDeclaration1()
+{
+ class Wrapper { QSharedPointer<ForwardDeclared> pointer; };
+}
+
+class ForwardDeclared { };
+void tst_QSharedPointer::forwardDeclaration2()
+{
+ class Wrapper { QSharedPointer<ForwardDeclared> pointer; };
+ Wrapper w;
+}
+
+void tst_QSharedPointer::memoryManagement()
+{
+ int generation = Data::generationCounter + 1;
+ int destructorCounter = Data::destructorCounter;
+
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data);
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ ptr = ptr;
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ {
+ QSharedPointer<Data> copy = ptr;
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(copy->generation, generation);
+
+ // copy goes out of scope, ptr continues
+ }
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ {
+ QWeakPointer<Data> weak = ptr;
+ weak = ptr;
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ weak = weak;
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ QSharedPointer<Data> strong = weak;
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(strong->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ // both weak and strong go out of scope
+ }
+ QCOMPARE(ptr->generation, generation);
+ QCOMPARE(Data::destructorCounter, destructorCounter);
+ QCOMPARE(Data::generationCounter, generation);
+
+ QWeakPointer<Data> weak = ptr;
+ ptr = QSharedPointer<Data>();
+
+ // destructor must have been called
+ QCOMPARE(Data::destructorCounter, destructorCounter + 1);
+ QVERIFY(ptr.isNull());
+ QVERIFY(weak.isNull());
+
+ // if we create a strong pointer from the weak, it must still be null
+ ptr = weak;
+ QVERIFY(ptr.isNull());
+ QVERIFY(ptr == 0);
+ QCOMPARE(ptr.data(), (Data*)0);
+}
+
+class DerivedData: public Data
+{
+public:
+ static int derivedDestructorCounter;
+ int moreData;
+ DerivedData() : moreData(0) { }
+ ~DerivedData() { ++derivedDestructorCounter; }
+
+ virtual void virtualDelete()
+ {
+ delete this;
+ }
+};
+int DerivedData::derivedDestructorCounter = 0;
+
+class Stuffing
+{
+public:
+ char buffer[16];
+ virtual ~Stuffing() { }
+};
+
+class DiffPtrDerivedData: public Stuffing, public Data
+{
+};
+
+void tst_QSharedPointer::downCast()
+{
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
+ QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
+ QSharedPointer<Data> other;
+
+ QVERIFY(ptr == baseptr);
+ QVERIFY(baseptr == ptr);
+ QVERIFY(! (ptr != baseptr));
+ QVERIFY(! (baseptr != ptr));
+
+ QVERIFY(ptr != other);
+ QVERIFY(other != ptr);
+ QVERIFY(! (ptr == other));
+ QVERIFY(! (other == ptr));
+ }
+
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
+ QSharedPointer<Data> baseptr = ptr;
+ }
+
+ int destructorCount;
+ destructorCount = DerivedData::derivedDestructorCounter;
+ {
+ QSharedPointer<Data> baseptr;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
+ baseptr = ptr;
+ QVERIFY(baseptr == ptr);
+ }
+ }
+ QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
+
+ destructorCount = DerivedData::derivedDestructorCounter;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
+ QWeakPointer<Data> baseptr = ptr;
+ QVERIFY(baseptr == ptr);
+
+ ptr = QSharedPointer<DerivedData>();
+ QVERIFY(baseptr.isNull());
+ }
+ QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
+
+ destructorCount = DerivedData::derivedDestructorCounter;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData);
+ QWeakPointer<DerivedData> weakptr(ptr);
+
+ QSharedPointer<Data> baseptr = weakptr;
+ QVERIFY(baseptr == ptr);
+ QWeakPointer<Data> baseweakptr = weakptr;
+ QVERIFY(baseweakptr == ptr);
+ }
+ QCOMPARE(DerivedData::derivedDestructorCounter, destructorCount + 1);
+}
+
+void tst_QSharedPointer::upCast()
+{
+ QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);
+
+ {
+ QSharedPointer<DerivedData> derivedptr = qSharedPointerCast<DerivedData>(baseptr);
+ QVERIFY(baseptr == derivedptr);
+ QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+
+ {
+ QWeakPointer<DerivedData> derivedptr = qWeakPointerCast<DerivedData>(baseptr);
+ QVERIFY(baseptr == derivedptr);
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+
+ {
+ QWeakPointer<Data> weakptr = baseptr;
+ QSharedPointer<DerivedData> derivedptr = qSharedPointerCast<DerivedData>(weakptr);
+ QVERIFY(baseptr == derivedptr);
+ QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+
+ {
+ QSharedPointer<DerivedData> derivedptr = baseptr.staticCast<DerivedData>();
+ QVERIFY(baseptr == derivedptr);
+ QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+}
+
+void tst_QSharedPointer::differentPointers()
+{
+ {
+ DiffPtrDerivedData *aData = new DiffPtrDerivedData;
+ Data *aBase = aData;
+ Q_ASSERT(aData == aBase);
+ Q_ASSERT(*reinterpret_cast<quintptr *>(&aData) != *reinterpret_cast<quintptr *>(&aBase));
+
+ QSharedPointer<DiffPtrDerivedData> ptr = QSharedPointer<DiffPtrDerivedData>(aData);
+ QSharedPointer<Data> baseptr = qSharedPointerCast<Data>(ptr);
+ QVERIFY(ptr == baseptr);
+ QVERIFY(ptr.data() == baseptr.data());
+ QVERIFY(ptr == aBase);
+ QVERIFY(ptr == aData);
+ QVERIFY(baseptr == aData);
+ QVERIFY(baseptr == aBase);
+ }
+
+ {
+ DiffPtrDerivedData *aData = new DiffPtrDerivedData;
+ Data *aBase = aData;
+ Q_ASSERT(aData == aBase);
+ Q_ASSERT(quintptr(&aData) != quintptr(&aBase));
+
+ QSharedPointer<Data> baseptr = QSharedPointer<Data>(aData);
+ QSharedPointer<DiffPtrDerivedData> ptr = qSharedPointerCast<DiffPtrDerivedData>(baseptr);
+ QVERIFY(ptr == baseptr);
+ QVERIFY(ptr.data() == baseptr.data());
+ QVERIFY(ptr == aBase);
+ QVERIFY(baseptr == aData);
+ }
+
+ {
+ DiffPtrDerivedData *aData = new DiffPtrDerivedData;
+ Data *aBase = aData;
+ Q_ASSERT(aData == aBase);
+ Q_ASSERT(quintptr(&aData) != quintptr(&aBase));
+
+ QSharedPointer<DiffPtrDerivedData> ptr = QSharedPointer<DiffPtrDerivedData>(aData);
+ QSharedPointer<Data> baseptr = ptr;
+ QVERIFY(ptr == baseptr);
+ QVERIFY(ptr.data() == baseptr.data());
+ QVERIFY(ptr == aBase);
+ QVERIFY(ptr == aData);
+ QVERIFY(baseptr == aData);
+ QVERIFY(baseptr == aBase);
+ }
+
+ // there is no possibility for different pointers in
+ // internal reference counting right now
+ //
+ // to do that, it's necessary to first implement the ability to
+ // call (virtual) functions, so that the two differing bases have
+ // the same reference counter
+}
+
+#ifndef QTEST_NO_RTTI
+void tst_QSharedPointer::dynamicCast()
+{
+ QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);
+
+ {
+ QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
+ QVERIFY(baseptr == derivedptr);
+ QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+
+ {
+ QWeakPointer<Data> weakptr = baseptr;
+ QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(weakptr);
+ QVERIFY(baseptr == derivedptr);
+ QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+
+ {
+ QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
+ QVERIFY(baseptr == derivedptr);
+ QCOMPARE(static_cast<Data *>(derivedptr.data()), baseptr.data());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+}
+
+void tst_QSharedPointer::dynamicCastFailure()
+{
+ QSharedPointer<Data> baseptr = QSharedPointer<Data>(new Data);
+ QVERIFY(dynamic_cast<DerivedData *>(baseptr.data()) == 0);
+
+ {
+ QSharedPointer<DerivedData> derivedptr = qSharedPointerDynamicCast<DerivedData>(baseptr);
+ QVERIFY(derivedptr.isNull());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+
+ {
+ QSharedPointer<DerivedData> derivedptr = baseptr.dynamicCast<DerivedData>();
+ QVERIFY(derivedptr.isNull());
+ }
+ QCOMPARE(int(baseptr.d->weakref), 1);
+ QCOMPARE(int(baseptr.d->strongref), 1);
+}
+#endif
+
+void tst_QSharedPointer::constCorrectness()
+{
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data);
+ QSharedPointer<const Data> cptr(ptr);
+ QSharedPointer<volatile Data> vptr(ptr);
+ cptr = ptr;
+ vptr = ptr;
+
+ ptr = qSharedPointerConstCast<Data>(cptr);
+ ptr = qSharedPointerConstCast<Data>(vptr);
+ ptr = cptr.constCast<Data>();
+ ptr = vptr.constCast<Data>();
+
+#if !defined(Q_CC_HPACC) && !defined(QT_ARCH_PARISC)
+ // the aCC series 3 compiler we have on the PA-RISC
+ // machine crashes compiling this code
+
+ QSharedPointer<const volatile Data> cvptr(ptr);
+ QSharedPointer<const volatile Data> cvptr2(cptr);
+ QSharedPointer<const volatile Data> cvptr3(vptr);
+ cvptr = ptr;
+ cvptr2 = cptr;
+ cvptr3 = vptr;
+ ptr = qSharedPointerConstCast<Data>(cvptr);
+ ptr = cvptr.constCast<Data>();
+#endif
+ }
+
+ {
+ Data *aData = new Data;
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(aData);
+ const QSharedPointer<Data> cptr = ptr;
+
+ ptr = cptr;
+ QSharedPointer<Data> other = qSharedPointerCast<Data>(cptr);
+ other = qSharedPointerDynamicCast<Data>(cptr);
+
+ QCOMPARE(cptr.data(), aData);
+ QCOMPARE(cptr.operator->(), aData);
+ }
+}
+
+static int customDeleterFnCallCount;
+void customDeleterFn(Data *ptr)
+{
+ ++customDeleterFnCallCount;
+ delete ptr;
+}
+
+template <typename T>
+struct CustomDeleter
+{
+ inline void operator()(T *ptr)
+ {
+ delete ptr;
+ ++callCount;
+ }
+ static int callCount;
+};
+template<typename T> int CustomDeleter<T>::callCount = 0;
+
+void tst_QSharedPointer::customDeleter()
+{
+ {
+ QSharedPointer<Data> ptr(new Data, &Data::doDelete);
+ QSharedPointer<Data> ptr2(new Data, &Data::alsoDelete);
+ QSharedPointer<Data> ptr3(new Data, &Data::virtualDelete);
+ }
+ {
+ QSharedPointer<DerivedData> ptr(new DerivedData, &Data::doDelete);
+ QSharedPointer<DerivedData> ptr2(new DerivedData, &Data::alsoDelete);
+ QSharedPointer<DerivedData> ptr3(new DerivedData, &Data::virtualDelete);
+ }
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
+ ptr.data();
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
+ QCOMPARE(customDeleterFnCallCount, 0);
+ ptr.clear();
+ QCOMPARE(customDeleterFnCallCount, 1);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
+ QCOMPARE(customDeleterFnCallCount, 0);
+ ptr = QSharedPointer<Data>(new Data);
+ QCOMPARE(customDeleterFnCallCount, 1);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new DerivedData, customDeleterFn);
+ ptr.data();
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, customDeleterFn);
+ ptr.data();
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<Data> other;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, customDeleterFn);
+ other = ptr;
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ customDeleterFnCallCount = 0;
+ {
+ QSharedPointer<Data> other;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, customDeleterFn);
+ other = ptr;
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 0);
+ }
+ QCOMPARE(customDeleterFnCallCount, 1);
+
+ CustomDeleter<Data> dataDeleter;
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
+ ptr.data();
+ QCOMPARE(dataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 1);
+
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
+ QSharedPointer<Data> other = ptr;
+ other.clear();
+ QCOMPARE(dataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 1);
+
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<Data> other;
+ {
+ QSharedPointer<Data> ptr = QSharedPointer<Data>(new Data, dataDeleter);
+ other = ptr;
+ QCOMPARE(dataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 1);
+
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, dataDeleter);
+ ptr.data();
+ QCOMPARE(dataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 1);
+
+ CustomDeleter<DerivedData> derivedDataDeleter;
+ derivedDataDeleter.callCount = 0;
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, derivedDataDeleter);
+ ptr.data();
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 1);
+
+ derivedDataDeleter.callCount = 0;
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<Data> other;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, dataDeleter);
+ other = ptr;
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 1);
+ QCOMPARE(derivedDataDeleter.callCount, 0);
+
+ derivedDataDeleter.callCount = 0;
+ dataDeleter.callCount = 0;
+ {
+ QSharedPointer<Data> other;
+ {
+ QSharedPointer<DerivedData> ptr = QSharedPointer<DerivedData>(new DerivedData, derivedDataDeleter);
+ other = ptr;
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 0);
+ }
+ QCOMPARE(dataDeleter.callCount, 0);
+ QCOMPARE(derivedDataDeleter.callCount, 1);
+}
+
+void tst_QSharedPointer::validConstructs()
+{
+ {
+ Data *aData = new Data;
+ QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);
+
+ ptr1 = ptr1; // valid
+
+ QSharedPointer<Data> ptr2(ptr1);
+
+ ptr1 = ptr2;
+ ptr2 = ptr1;
+
+ ptr1 = QSharedPointer<Data>();
+ ptr1 = ptr2;
+ }
+}
+
+typedef bool (QTest::QExternalTest:: * TestFunction)(const QByteArray &body);
+Q_DECLARE_METATYPE(TestFunction)
+void tst_QSharedPointer::invalidConstructs_data()
+{
+ QTest::addColumn<TestFunction>("testFunction");
+ QTest::addColumn<QString>("code");
+ QTest::newRow("sanity-checking") << &QTest::QExternalTest::tryCompile << "";
+
+ // QSharedPointer<void> is not allowed
+ QTest::newRow("void") << &QTest::QExternalTest::tryCompileFail << "QSharedPointer<void> ptr;";
+
+ // implicit initialization
+ QTest::newRow("implicit-initialization1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> ptr = new Data;";
+ QTest::newRow("implicit-initialization2")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> ptr;"
+ "ptr = new Data;";
+ QTest::newRow("implicit-initialization3")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QWeakPointer<Data> ptr = new Data;";
+ QTest::newRow("implicit-initialization1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QWeakPointer<Data> ptr;"
+ "ptr = new Data;";
+
+ // use of forward-declared class
+ QTest::newRow("forward-declaration")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<ForwardDeclared> ptr;";
+
+ // upcast without cast operator:
+ QTest::newRow("upcast1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);\n"
+ "QSharedPointer<DerivedData> ptr(baseptr);";
+ QTest::newRow("upcast2")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> baseptr = QSharedPointer<Data>(new DerivedData);\n"
+ "QSharedPointer<DerivedData> ptr;\n"
+ "ptr = baseptr;";
+
+ // dropping of const
+ QTest::newRow("const-dropping1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
+ "QSharedPointer<Data> ptr(baseptr);";
+ QTest::newRow("const-dropping2")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<const Data> baseptr = QSharedPointer<const Data>(new Data);\n"
+ "QSharedPointer<Data> ptr;"
+ "ptr = baseptr;";
+
+ // arithmethics through automatic cast operators
+ QTest::newRow("arithmethic1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<int> a;"
+ "QSharedPointer<Data> b;\n"
+ "if (a == b) return;";
+ QTest::newRow("arithmethic2")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<int> a;"
+ "QSharedPointer<Data> b;\n"
+ "if (a + b) return;";
+
+ // two objects with the same pointer
+ QTest::newRow("same-pointer")
+ << &QTest::QExternalTest::tryRunFail
+ << "Data *aData = new Data;\n"
+ "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);\n"
+ "QSharedPointer<Data> ptr2 = QSharedPointer<Data>(aData);\n";
+
+ // re-creation:
+ QTest::newRow("re-creation")
+ << &QTest::QExternalTest::tryRunFail
+ << "Data *aData = new Data;\n"
+ "QSharedPointer<Data> ptr1 = QSharedPointer<Data>(aData);"
+ "ptr1 = QSharedPointer<Data>(aData);";
+
+ // any type of cast for unrelated types:
+ // (we have no reinterpret_cast)
+ QTest::newRow("invalid-cast1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> ptr1;\n"
+ "QSharedPointer<int> ptr2 = qSharedPointerCast<int>(ptr1);";
+ QTest::newRow("invalid-cast2")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> ptr1;\n"
+ "QSharedPointer<int> ptr2 = qSharedPointerDynamicCast<int>(ptr1);";
+ QTest::newRow("implicit-initialization1")
+ << &QTest::QExternalTest::tryCompileFail
+ << "QSharedPointer<Data> ptr1;\n"
+ "QSharedPointer<int> ptr2 = qSharedPointerConstCast<int>(ptr1);";
+}
+
+void tst_QSharedPointer::invalidConstructs()
+{
+#ifdef Q_CC_MINGW
+ QSKIP("The maintainer of QSharedPointer: 'We don't know what the problem is so skip the tests.'", SkipAll);
+#endif
+#ifdef QTEST_CROSS_COMPILED
+ QSKIP("This test does not work on cross compiled systems", SkipAll);
+#endif
+
+ QTest::QExternalTest test;
+ test.setDebugMode(true);
+ test.setQtModules(QTest::QExternalTest::QtCore);
+ test.setProgramHeader(
+ "#include <QtCore/qsharedpointer.h>\n"
+ "\n"
+ "struct Data { int i; };\n"
+ "struct DerivedData: public Data { int j; };\n"
+ "struct ForwardDeclared;");
+
+ QFETCH(QString, code);
+ static bool sane = true;
+ if (code.isEmpty()) {
+ static const char snippet[] = "QSharedPointer<Data> baseptr; QSharedPointer<DerivedData> ptr;";
+ if (!test.tryCompile("")
+ || !test.tryRun("")
+ || !test.tryRunFail("exit(1);")
+ || !test.tryCompile(snippet)
+ || !test.tryLink(snippet)
+ || !test.tryRun(snippet)) {
+ sane = false;
+ qWarning("Sanity checking failed\nCode:\n%s\n",
+ qPrintable(test.errorReport()));
+ }
+ }
+ if (!sane)
+ QFAIL("External testing failed sanity checking, cannot proceed");
+
+ QFETCH(TestFunction, testFunction);
+
+ QByteArray body = code.toLatin1();
+
+ if (!(test.*testFunction)(body)) {
+ qWarning("External code testing failed\nCode:\n%s\n", body.constData());
+ QFAIL("Fail");
+ }
+}
+
+QTEST_MAIN(tst_QSharedPointer)
+
+#include "tst_qsharedpointer.moc"