Commit ef403a45 authored by Nikolai Kosjar's avatar Nikolai Kosjar Committed by Erik Verbruggen

GenericProjectManager: Tests: Clean up

* Get rid of CppModelManagerHelper.
  Now we simply use CppModelManager::projectInfo(someProject).isValid() to
  test whether a project is loaded.

* Copy project data to temporary dir before opening the projects.
  This avoids creating *.user files in the Qt Creator source tree and
  annoying pop ups on test start.

Change-Id: I1a57441ca2099beb6bb96cf620390d669fb47601
Reviewed-by: default avatarChristian Stenger <christian.stenger@theqtcompany.com>
parent 613304ed
......@@ -31,6 +31,8 @@
#include "cpptoolstestcase.h"
#include <coreplugin/editormanager/editormanager.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <texteditor/texteditor.h>
#include <texteditor/codeassist/iassistproposal.h>
#include <texteditor/codeassist/iassistproposalmodel.h>
......@@ -40,6 +42,8 @@
#include <QtTest>
using namespace ProjectExplorer;
static bool closeEditorsWithoutGarbageCollectorInvocation(const QList<Core::IEditor *> &editors)
{
CppTools::CppModelManager::instance()->enableGarbageCollector(false);
......@@ -181,6 +185,24 @@ QList<CPlusPlus::Document::Ptr> 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)
{
......
......@@ -37,6 +37,7 @@
#include <coreplugin/editormanager/ieditor.h>
#include <QStringList>
#include <QTemporaryDir>
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<CPlusPlus::Document::Ptr> 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<ProjectExplorer::Project *> 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:
......
/****************************************************************************
**
** 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 <QCoreApplication>
#include <QTest>
#include <QThread>
using namespace CppTools;
using namespace GenericProjectManager::Internal::Tests;
CppModelManagerHelper::CppModelManagerHelper(QObject *parent)
: QObject(parent)
, m_spy(cppModelManager(), SIGNAL(sourceFilesRefreshed(const QSet<QString> &)))
{
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<QString> &files)
{
m_refreshedSourceFiles.unite(files);
}
/****************************************************************************
**
** 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 <cpptools/cppmodelmanager.h>
#include <QObject>
#include <QSignalSpy>
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<QString> &files);
QSet<QString> m_refreshedSourceFiles;
QSignalSpy m_spy;
};
} // Tests namespace
} // Internal namespace
} // GenericProjectManager namespace
#endif // CPPMODELMANAGERHELPER_H
......@@ -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\\\"
}
......@@ -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) + '"'])
}
......
......@@ -28,92 +28,52 @@
**
****************************************************************************/
#include "cppmodelmanagerhelper.h"
#include "genericprojectplugin.h"
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/session.h>
#include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolstestcase.h>
#include <QFileInfo>
#include <QTemporaryDir>
#include <QTest>
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<Project *> 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<CppTools::ProjectFile> &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);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment