AutoTest: Try harder to find relevant build targets

If there are tests defined or registered inside libraries
we ended up trying to execute the library or nothing at all.
If possible try to find correct build targets for such cases.

Change-Id: I58e9edb7f858e3e5407ece6fcb8782f5a129acd0
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
Christian Stenger
2017-09-13 10:32:39 +02:00
parent fb063a09be
commit 3c602b32d4
5 changed files with 53 additions and 15 deletions

View File

@@ -296,13 +296,13 @@ QSet<QString> GTestTreeItem::internalTargets() const
const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject()); const auto projectInfo = cppMM->projectInfo(ProjectExplorer::SessionManager::startupProject());
const QString file = filePath(); const QString file = filePath();
for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) { for (const CppTools::ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
if (projectPart->buildTargetType != CppTools::ProjectPart::Executable)
continue;
if (projectPart->projectFile == proFile() if (projectPart->projectFile == proFile()
&& Utils::anyOf(projectPart->files, [&file] (const CppTools::ProjectFile &pf) { && Utils::anyOf(projectPart->files, [&file] (const CppTools::ProjectFile &pf) {
return pf.path == file; return pf.path == file;
})) { })) {
result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile); result.insert(projectPart->buildSystemTarget + '|' + projectPart->projectFile);
if (projectPart->buildTargetType != CppTools::ProjectPart::Executable)
result.unite(TestTreeItem::dependingInternalTargets(cppMM, file));
} }
} }
return result; return result;

View File

@@ -30,6 +30,7 @@
#include <cplusplus/Icons.h> #include <cplusplus/Icons.h>
#include <cpptools/cppmodelmanager.h> #include <cpptools/cppmodelmanager.h>
#include <cpptools/cpptoolsreuse.h>
#include <texteditor/texteditor.h> #include <texteditor/texteditor.h>
#include <QIcon> #include <QIcon>
@@ -286,12 +287,12 @@ bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const
QSet<QString> TestTreeItem::internalTargets() const QSet<QString> TestTreeItem::internalTargets() const
{ {
auto cppMM = CppTools::CppModelManager::instance(); auto cppMM = CppTools::CppModelManager::instance();
const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(filePath()); const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(m_filePath);
QSet<QString> targets; QSet<QString> targets;
for (const CppTools::ProjectPart::Ptr part : projectParts) { for (const CppTools::ProjectPart::Ptr part : projectParts) {
if (part->buildTargetType != CppTools::ProjectPart::Executable)
continue;
targets.insert(part->buildSystemTarget + '|' + part->projectFile); targets.insert(part->buildSystemTarget + '|' + part->projectFile);
if (part->buildTargetType != CppTools::ProjectPart::Executable)
targets.unite(TestTreeItem::dependingInternalTargets(cppMM, m_filePath));
} }
return targets; return targets;
} }
@@ -359,5 +360,28 @@ TestTreeItem *TestTreeItem::findChildBy(CompareFunction compare) const
return nullptr; return nullptr;
} }
/*
* try to find build system target that depends on the given file - if the file is no header
* try to find the corresponding header and use this instead to find the respective target
*/
QSet<QString> TestTreeItem::dependingInternalTargets(CppTools::CppModelManager *cppMM,
const QString &file)
{
QSet<QString> result;
QTC_ASSERT(cppMM, return result);
const CPlusPlus::Snapshot snapshot = cppMM->snapshot();
QTC_ASSERT(snapshot.contains(file), return result);
bool wasHeader;
const QString correspondingFile
= CppTools::correspondingHeaderOrSource(file, &wasHeader, CppTools::CacheUsage::ReadOnly);
const Utils::FileNameList dependingFiles = snapshot.filesDependingOn(
wasHeader ? file : correspondingFile);
for (const Utils::FileName &fn : dependingFiles) {
for (const CppTools::ProjectPart::Ptr part : cppMM->projectPart(fn))
result.insert(part->buildSystemTarget + '|' + part->projectFile);
}
return result;
}
} // namespace Internal } // namespace Internal
} // namespace Autotest } // namespace Autotest

View File

@@ -28,6 +28,7 @@
#include <utils/treemodel.h> #include <utils/treemodel.h>
#include <QList> #include <QList>
#include <QSet>
#include <QString> #include <QString>
#include <QMetaType> #include <QMetaType>
@@ -40,6 +41,8 @@ namespace {
}; };
} }
namespace CppTools { class CppModelManager; }
namespace Autotest { namespace Autotest {
namespace Internal { namespace Internal {
@@ -114,6 +117,8 @@ public:
protected: protected:
typedef std::function<bool(const TestTreeItem *)> CompareFunction; typedef std::function<bool(const TestTreeItem *)> CompareFunction;
TestTreeItem *findChildBy(CompareFunction compare) const; TestTreeItem *findChildBy(CompareFunction compare) const;
static QSet<QString> dependingInternalTargets(CppTools::CppModelManager *cppMM,
const QString &file);
private: private:
void revalidateCheckState(); void revalidateCheckState();

View File

@@ -357,7 +357,8 @@ static int commonFilePathLength(const QString &s1, const QString &s2)
static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo, static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
const QStringList &candidateFileNames, const QStringList &candidateFileNames,
const ProjectExplorer::Project *project) const ProjectExplorer::Project *project,
CacheUsage cacheUsage)
{ {
QString bestFileName; QString bestFileName;
int compareValue = 0; int compareValue = 0;
@@ -376,8 +377,10 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
if (!bestFileName.isEmpty()) { if (!bestFileName.isEmpty()) {
const QFileInfo candidateFi(bestFileName); const QFileInfo candidateFi(bestFileName);
QTC_ASSERT(candidateFi.isFile(), return QString()); QTC_ASSERT(candidateFi.isFile(), return QString());
if (cacheUsage == CacheUsage::ReadWrite) {
m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath(); m_headerSourceMapping[fileInfo.absoluteFilePath()] = candidateFi.absoluteFilePath();
m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath(); m_headerSourceMapping[candidateFi.absoluteFilePath()] = fileInfo.absoluteFilePath();
}
return candidateFi.absoluteFilePath(); return candidateFi.absoluteFilePath();
} }
@@ -386,7 +389,7 @@ static QString correspondingHeaderOrSourceInProject(const QFileInfo &fileInfo,
} // namespace Internal } // namespace Internal
QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader) QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader, CacheUsage cacheUsage)
{ {
using namespace Internal; using namespace Internal;
@@ -437,9 +440,11 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath); const QString normalized = Utils::FileUtils::normalizePathName(candidateFilePath);
const QFileInfo candidateFi(normalized); const QFileInfo candidateFi(normalized);
if (candidateFi.isFile()) { if (candidateFi.isFile()) {
if (cacheUsage == CacheUsage::ReadWrite) {
m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath(); m_headerSourceMapping[fi.absoluteFilePath()] = candidateFi.absoluteFilePath();
if (!isHeader || !baseName.endsWith(privateHeaderSuffix)) if (!isHeader || !baseName.endsWith(privateHeaderSuffix))
m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath(); m_headerSourceMapping[candidateFi.absoluteFilePath()] = fi.absoluteFilePath();
}
return candidateFi.absoluteFilePath(); return candidateFi.absoluteFilePath();
} }
} }
@@ -449,7 +454,7 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject(); ProjectExplorer::Project *currentProject = ProjectExplorer::ProjectTree::currentProject();
if (currentProject) { if (currentProject) {
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
currentProject); currentProject, cacheUsage);
if (!path.isEmpty()) if (!path.isEmpty())
return path; return path;
@@ -462,7 +467,8 @@ QString correspondingHeaderOrSource(const QString &fileName, bool *wasHeader)
if (project == currentProject) if (project == currentProject)
continue; // We have already checked the current project. continue; // We have already checked the current project.
const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames, project); const QString path = correspondingHeaderOrSourceInProject(fi, candidateFileNames,
project, cacheUsage);
if (!path.isEmpty()) if (!path.isEmpty())
return path; return path;
} }

View File

@@ -68,7 +68,10 @@ bool CPPTOOLS_EXPORT isOwnershipRAIIType(CPlusPlus::Symbol *symbol,
const CPlusPlus::Macro CPPTOOLS_EXPORT *findCanonicalMacro(const QTextCursor &cursor, const CPlusPlus::Macro CPPTOOLS_EXPORT *findCanonicalMacro(const QTextCursor &cursor,
CPlusPlus::Document::Ptr document); CPlusPlus::Document::Ptr document);
QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0); enum class CacheUsage { ReadWrite, ReadOnly };
QString CPPTOOLS_EXPORT correspondingHeaderOrSource(const QString &fileName, bool *wasHeader = 0,
CacheUsage cacheUsage = CacheUsage::ReadWrite);
void CPPTOOLS_EXPORT switchHeaderSource(); void CPPTOOLS_EXPORT switchHeaderSource();
class CppCodeModelSettings; class CppCodeModelSettings;