diff --git a/src/plugins/cpptools/cpptoolstestcase.cpp b/src/plugins/cpptools/cpptoolstestcase.cpp index 00750ed0d9c..0102384aa8e 100644 --- a/src/plugins/cpptools/cpptoolstestcase.cpp +++ b/src/plugins/cpptools/cpptoolstestcase.cpp @@ -31,6 +31,8 @@ #include "cpptoolstestcase.h" #include +#include +#include #include #include #include @@ -40,6 +42,8 @@ #include +using namespace ProjectExplorer; + static bool closeEditorsWithoutGarbageCollectorInvocation(const QList &editors) { CppTools::CppModelManager::instance()->enableGarbageCollector(false); @@ -181,6 +185,24 @@ QList TestCase::waitForFilesInGlobalSnapshot( return result; } +bool TestCase::waitUntilCppModelManagerIsAwareOf(Project *project, int timeOut) +{ + if (!project) + return false; + + QTime t; + t.start(); + + CppModelManager *modelManager = CppModelManager::instance(); + forever { + if (modelManager->projectInfo(project).isValid()) + return true; + if (t.elapsed() > timeOut) + return false; + QCoreApplication::processEvents(); + } +} + bool TestCase::writeFile(const QString &filePath, const QByteArray &contents) { Utils::FileSaver saver(filePath); @@ -192,6 +214,60 @@ bool TestCase::writeFile(const QString &filePath, const QByteArray &contents) return true; } +ProjectOpenerAndCloser::ProjectOpenerAndCloser() +{ + QVERIFY(!SessionManager::hasProjects()); +} + +ProjectOpenerAndCloser::~ProjectOpenerAndCloser() +{ + foreach (Project *project, m_openProjects) + ProjectExplorerPlugin::unloadProject(project); +} + +ProjectInfo ProjectOpenerAndCloser::open(const QString &projectFile) +{ + QString error; + Project *project = ProjectExplorerPlugin::openProject(projectFile, &error); + if (!error.isEmpty()) + qWarning() << error; + if (!project) + return ProjectInfo(); + m_openProjects.append(project); + + if (TestCase::waitUntilCppModelManagerIsAwareOf(project)) + return CppModelManager::instance()->projectInfo(project); + + return ProjectInfo(); +} + +TemporaryCopiedDir::TemporaryCopiedDir(const QString &sourceDirPath) + : m_temporaryDir(QDir::tempPath() + QLatin1String("/qtcreator-tests-XXXXXX")) + , m_isValid(m_temporaryDir.isValid()) +{ + if (!m_isValid) + return; + + if (!sourceDirPath.isEmpty()) { + QFileInfo fi(sourceDirPath); + if (!fi.exists() || !fi.isReadable()) { + m_isValid = false; + return; + } + + if (!Utils::FileUtils::copyRecursively(Utils::FileName::fromString(sourceDirPath), + Utils::FileName::fromString(path()))) { + m_isValid = false; + return; + } + } +} + +QString TemporaryCopiedDir::absolutePath(const QByteArray &relativePath) const +{ + return m_temporaryDir.path() + QLatin1Char('/') + QString::fromUtf8(relativePath); +} + FileWriterAndRemover::FileWriterAndRemover(const QString &filePath, const QByteArray &contents) : m_filePath(filePath) { diff --git a/src/plugins/cpptools/cpptoolstestcase.h b/src/plugins/cpptools/cpptoolstestcase.h index 5c90cf73b9d..d20950ebb41 100644 --- a/src/plugins/cpptools/cpptoolstestcase.h +++ b/src/plugins/cpptools/cpptoolstestcase.h @@ -37,6 +37,7 @@ #include #include +#include namespace CPlusPlus { class Document; @@ -44,6 +45,7 @@ class Snapshot; } namespace Core { class IEditor; } +namespace ProjectExplorer { class Project; } namespace TextEditor { class BaseTextEditor; @@ -87,6 +89,8 @@ public: static CPlusPlus::Snapshot globalSnapshot(); static bool garbageCollectGlobalSnapshot(); + static bool waitUntilCppModelManagerIsAwareOf(ProjectExplorer::Project *project, + int timeOut = 30 * 1000 /*= 30 secs*/); static CPlusPlus::Document::Ptr waitForFileInGlobalSnapshot(const QString &filePath); static QList waitForFilesInGlobalSnapshot( const QStringList &filePaths); @@ -102,6 +106,32 @@ private: bool m_runGarbageCollector; }; +class CPPTOOLS_EXPORT ProjectOpenerAndCloser +{ +public: + ProjectOpenerAndCloser(); + ~ProjectOpenerAndCloser(); // Closes opened projects + + ProjectInfo open(const QString &projectFile); + +private: + QList m_openProjects; +}; + +class CPPTOOLS_EXPORT TemporaryCopiedDir +{ +public: + TemporaryCopiedDir(const QString &sourceDirPath); + + bool isValid() const { return m_isValid; } + QString path() const { return m_temporaryDir.path(); } + QString absolutePath(const QByteArray &relativePath) const; + +private: + QTemporaryDir m_temporaryDir; + bool m_isValid; +}; + class FileWriterAndRemover { public: diff --git a/src/plugins/genericprojectmanager/cppmodelmanagerhelper.cpp b/src/plugins/genericprojectmanager/cppmodelmanagerhelper.cpp deleted file mode 100644 index e2e2560fc54..00000000000 --- a/src/plugins/genericprojectmanager/cppmodelmanagerhelper.cpp +++ /dev/null @@ -1,74 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** 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 Digia. For licensing terms and -** conditions see http://www.qt.io/licensing. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#include "cppmodelmanagerhelper.h" - -#include -#include -#include - -using namespace CppTools; -using namespace GenericProjectManager::Internal::Tests; - -CppModelManagerHelper::CppModelManagerHelper(QObject *parent) - : QObject(parent) - , m_spy(cppModelManager(), SIGNAL(sourceFilesRefreshed(const QSet &))) -{ - connect(cppModelManager(), &CppModelManager::sourceFilesRefreshed, - this, &CppModelManagerHelper::onSourceFilesRefreshed); -} - -CppModelManager *CppModelManagerHelper::cppModelManager() -{ - return CppModelManager::instance(); -} - -void CppModelManagerHelper::waitForSourceFilesRefreshed(const QString &file, int timeOut) -{ - waitForSourceFilesRefreshed(QStringList() << file, timeOut); -} - -void CppModelManagerHelper::waitForSourceFilesRefreshed(const QStringList &files, int timeOut) -{ - QTime t; - t.start(); - - foreach (const QString &file, files) { - while (!m_refreshedSourceFiles.contains(file)) - QCoreApplication::processEvents(); - QVERIFY(t.elapsed() <= timeOut); - } - QCOMPARE(m_spy.count(), 1); -} - -void CppModelManagerHelper::onSourceFilesRefreshed(const QSet &files) -{ - m_refreshedSourceFiles.unite(files); -} diff --git a/src/plugins/genericprojectmanager/cppmodelmanagerhelper.h b/src/plugins/genericprojectmanager/cppmodelmanagerhelper.h deleted file mode 100644 index 8905d46454b..00000000000 --- a/src/plugins/genericprojectmanager/cppmodelmanagerhelper.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). -** Contact: http://www.qt-project.org/legal -** -** This file is part of Qt Creator. -** -** 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 Digia. For licensing terms and -** conditions see http://www.qt.io/licensing. For further information -** use the contact form at http://www.qt.io/contact-us. -** -** 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 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Digia gives you certain additional -** rights. These rights are described in the Digia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -****************************************************************************/ - -#ifndef CPPMODELMANAGERHELPER_H -#define CPPMODELMANAGERHELPER_H - -#include - -#include -#include - -namespace GenericProjectManager { -namespace Internal { -namespace Tests { - -class CppModelManagerHelper : public QObject -{ - Q_OBJECT -public: - explicit CppModelManagerHelper(QObject *parent = 0); - - static CppTools::CppModelManager *cppModelManager(); - - enum { defaultTimeOut = 30 * 1000 }; // 30 secs - void waitForSourceFilesRefreshed(const QString &file = QString(), int timeOut = defaultTimeOut); - void waitForSourceFilesRefreshed(const QStringList &files, int timeOut = defaultTimeOut); - -private: - void onSourceFilesRefreshed(const QSet &files); - - QSet m_refreshedSourceFiles; - QSignalSpy m_spy; -}; - -} // Tests namespace -} // Internal namespace -} // GenericProjectManager namespace - -#endif // CPPMODELMANAGERHELPER_H diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.pro b/src/plugins/genericprojectmanager/genericprojectmanager.pro index 72911ca6889..c0da34edc92 100644 --- a/src/plugins/genericprojectmanager/genericprojectmanager.pro +++ b/src/plugins/genericprojectmanager/genericprojectmanager.pro @@ -23,7 +23,6 @@ RESOURCES += genericproject.qrc FORMS += genericmakestep.ui equals(TEST, 1) { - SOURCES += genericprojectplugin_test.cpp cppmodelmanagerhelper.cpp - HEADERS += cppmodelmanagerhelper.h + SOURCES += genericprojectplugin_test.cpp DEFINES += SRCDIR=\\\"$$PWD\\\" } diff --git a/src/plugins/genericprojectmanager/genericprojectmanager.qbs b/src/plugins/genericprojectmanager/genericprojectmanager.qbs index 62572d4457b..9de35a1d494 100644 --- a/src/plugins/genericprojectmanager/genericprojectmanager.qbs +++ b/src/plugins/genericprojectmanager/genericprojectmanager.qbs @@ -40,10 +40,7 @@ QtcPlugin { Group { name: "Tests" condition: project.testsEnabled - files: [ - "cppmodelmanagerhelper.cpp", "cppmodelmanagerhelper.h", - "genericprojectplugin_test.cpp", - ] + files: [ "genericprojectplugin_test.cpp" ] cpp.defines: outer.concat(['SRCDIR="' + FileInfo.path(filePath) + '"']) } diff --git a/src/plugins/genericprojectmanager/genericprojectplugin_test.cpp b/src/plugins/genericprojectmanager/genericprojectplugin_test.cpp index 5b45469fddc..600c7d29092 100644 --- a/src/plugins/genericprojectmanager/genericprojectplugin_test.cpp +++ b/src/plugins/genericprojectmanager/genericprojectplugin_test.cpp @@ -28,92 +28,52 @@ ** ****************************************************************************/ -#include "cppmodelmanagerhelper.h" #include "genericprojectplugin.h" #include #include #include +#include +#include + #include +#include #include using namespace CppTools; +using namespace CppTools::Tests; using namespace GenericProjectManager; using namespace GenericProjectManager::Internal; -using namespace GenericProjectManager::Internal::Tests; using namespace ProjectExplorer; -inline static QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); } -inline static QString projectFilePath(const QString &project) +namespace { + +inline QString _(const QByteArray &ba) { return QString::fromLatin1(ba, ba.size()); } +inline QString sourceProjectPath(const QString &project) { const QString fileName(_(SRCDIR "/../../../tests/genericprojectmanager/") + project); return QFileInfo(fileName).absoluteFilePath(); } -namespace { -class ProjectExplorerHelper -{ -public: - ProjectExplorerHelper() - { - QVERIFY(!SessionManager::hasProjects()); - } - - ~ProjectExplorerHelper() - { - foreach (Project *project, m_openProjects) - ProjectExplorerPlugin::unloadProject(project); - } - - Project *openProject(const QString &projectFile) - { - QString error; - Project *project = ProjectExplorerPlugin::openProject(projectFile, &error); - if (!error.isEmpty()) - qWarning() << error; - if (!project) - return 0; - m_openProjects.append(project); - return project; - } - -private: - QList m_openProjects; -}; } // anonymous namespace -static ProjectInfo setupProject(const QByteArray &projectFile, const QByteArray &mainFile, - ProjectExplorerHelper &pHelper) -{ - CppModelManagerHelper cppHelper; - Project *project = pHelper.openProject(projectFilePath(_(projectFile))); - if (!project) - return ProjectInfo(); - - // Wait only for a single file: we don't really care if the file is refreshed or not, but at - // this point we know that the C++ model manager got notified of all project parts and we can - // retrieve them for inspection. - cppHelper.waitForSourceFilesRefreshed(projectFilePath(_(mainFile))); - - CppModelManager *mm = cppHelper.cppModelManager(); - return mm->projectInfo(project); -} - void GenericProjectPlugin::test_simple() { - ProjectExplorerHelper pHelper; + TemporaryCopiedDir temporaryDir(sourceProjectPath(_("testdata_simpleproject"))); + QVERIFY(temporaryDir.isValid()); + const QString mainFile = temporaryDir.absolutePath("main.cpp"); + const QString projectFile = temporaryDir.absolutePath("simpleproject.creator"); - const QByteArray mainFile("testdata_simpleproject/main.cpp"); - ProjectInfo pInfo( - setupProject("testdata_simpleproject/simpleproject.creator", mainFile, pHelper)); + ProjectOpenerAndCloser projects; + const ProjectInfo pInfo = projects.open(projectFile); QVERIFY(pInfo.isValid()); QCOMPARE(pInfo.projectParts().size(), 1); ProjectPart::Ptr pPart = pInfo.projectParts().first(); QVERIFY(pPart); QCOMPARE(pPart->files.size(), 1); - QCOMPARE(pPart->files.first().path, projectFilePath(_(mainFile))); + QCOMPARE(pPart->files.first().path, mainFile); QCOMPARE(pPart->files.first().kind, ProjectFile::CXXSource); } @@ -133,11 +93,12 @@ static QStringList simplify(const QList &files, const QSt void GenericProjectPlugin::test_mixed1() { - ProjectExplorerHelper pHelper; - ProjectInfo pInfo( - setupProject("testdata_mixedproject1/mixedproject1.creator", - "testdata_mixedproject1/main.cpp", - pHelper)); + TemporaryCopiedDir temporaryDir(sourceProjectPath(_("testdata_mixedproject1/"))); + QVERIFY(temporaryDir.isValid()); + const QString projectFile = temporaryDir.absolutePath("mixedproject1.creator"); + + ProjectOpenerAndCloser projects; + const ProjectInfo pInfo = projects.open(projectFile); QVERIFY(pInfo.isValid()); QCOMPARE(pInfo.projectParts().size(), 3); @@ -147,9 +108,10 @@ void GenericProjectPlugin::test_mixed1() return p1->displayName < p2->displayName; }); - QStringList part0files = simplify(parts[0]->files,projectFilePath(_("testdata_mixedproject1/"))); - QStringList part1files = simplify(parts[1]->files,projectFilePath(_("testdata_mixedproject1/"))); - QStringList part2files = simplify(parts[2]->files,projectFilePath(_("testdata_mixedproject1/"))); + const QString dirPathWithSlash = temporaryDir.path() + QLatin1Char('/'); + const QStringList part0files = simplify(parts[0]->files, dirPathWithSlash); + const QStringList part1files = simplify(parts[1]->files, dirPathWithSlash); + const QStringList part2files = simplify(parts[2]->files, dirPathWithSlash); QCOMPARE(parts[0]->displayName, _("mixedproject1 (C++11)")); QCOMPARE(parts[0]->files.size(), 4); @@ -178,11 +140,12 @@ void GenericProjectPlugin::test_mixed1() void GenericProjectPlugin::test_mixed2() { - ProjectExplorerHelper pHelper; - ProjectInfo pInfo( - setupProject("testdata_mixedproject2/mixedproject2.creator", - "testdata_mixedproject2/main.cpp", - pHelper)); + TemporaryCopiedDir temporaryDir(sourceProjectPath(_("testdata_mixedproject2/"))); + QVERIFY(temporaryDir.isValid()); + const QString projectFile = temporaryDir.absolutePath("mixedproject2.creator"); + + ProjectOpenerAndCloser projects; + const ProjectInfo pInfo = projects.open(projectFile); QVERIFY(pInfo.isValid()); QCOMPARE(pInfo.projectParts().size(), 2); @@ -192,8 +155,9 @@ void GenericProjectPlugin::test_mixed2() return p1->displayName < p2->displayName; }); - QStringList part0files = simplify(parts[0]->files,projectFilePath(_("testdata_mixedproject2/"))); - QStringList part1files = simplify(parts[1]->files,projectFilePath(_("testdata_mixedproject2/"))); + const QString dirPathWithSlash = temporaryDir.path() + QLatin1Char('/'); + const QStringList part0files = simplify(parts[0]->files, dirPathWithSlash); + const QStringList part1files = simplify(parts[1]->files, dirPathWithSlash); QCOMPARE(parts[0]->displayName, _("mixedproject2 (C++11)")); QCOMPARE(parts[0]->files.size(), 2);