2016-05-11 13:02:42 +02:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** Copyright (C) 2016 The Qt Company Ltd.
|
|
|
|
|
** Contact: https://www.qt.io/licensing/
|
|
|
|
|
**
|
|
|
|
|
** 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 The Qt Company. For licensing terms
|
|
|
|
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
|
|
|
|
** information use the contact form at https://www.qt.io/contact-us.
|
|
|
|
|
**
|
|
|
|
|
** GNU General Public License Usage
|
|
|
|
|
** Alternatively, this file may be used under the terms of the GNU
|
|
|
|
|
** General Public License version 3 as published by the Free Software
|
|
|
|
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
|
|
|
|
** included in the packaging of this file. Please review the following
|
|
|
|
|
** information to ensure the GNU General Public License requirements will
|
|
|
|
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
|
|
|
|
**
|
|
|
|
|
****************************************************************************/
|
|
|
|
|
|
2016-06-06 12:17:19 +02:00
|
|
|
#include "gtestparser.h"
|
|
|
|
|
#include "gtesttreeitem.h"
|
2016-05-11 13:02:42 +02:00
|
|
|
#include "gtestvisitors.h"
|
|
|
|
|
#include "gtest_utils.h"
|
|
|
|
|
#include "../autotest_utils.h"
|
|
|
|
|
|
|
|
|
|
namespace Autotest {
|
|
|
|
|
namespace Internal {
|
|
|
|
|
|
2016-06-06 12:17:19 +02:00
|
|
|
TestTreeItem *GTestParseResult::createTestTreeItem() const
|
2016-05-11 13:02:42 +02:00
|
|
|
{
|
2017-01-05 12:03:42 +01:00
|
|
|
if (itemType != TestTreeItem::TestCase && itemType != TestTreeItem::TestFunctionOrSet)
|
|
|
|
|
return nullptr;
|
|
|
|
|
GTestTreeItem *item = new GTestTreeItem(name, fileName, itemType);
|
|
|
|
|
item->setProFile(proFile);
|
|
|
|
|
item->setLine(line);
|
|
|
|
|
item->setColumn(column);
|
|
|
|
|
|
|
|
|
|
if (parameterized)
|
|
|
|
|
item->setState(GTestTreeItem::Parameterized);
|
|
|
|
|
if (typed)
|
|
|
|
|
item->setState(GTestTreeItem::Typed);
|
|
|
|
|
if (disabled)
|
|
|
|
|
item->setState(GTestTreeItem::Disabled);
|
2017-02-13 10:05:06 +01:00
|
|
|
for (const TestParseResult *testSet : children)
|
2017-01-05 12:03:42 +01:00
|
|
|
item->appendChild(testSet->createTestTreeItem());
|
|
|
|
|
return item;
|
2016-05-11 13:02:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool includesGTest(const CPlusPlus::Document::Ptr &doc,
|
|
|
|
|
const CPlusPlus::Snapshot &snapshot)
|
|
|
|
|
{
|
2016-09-29 12:15:43 +02:00
|
|
|
static const QString gtestH("gtest/gtest.h");
|
2017-02-13 10:05:06 +01:00
|
|
|
for (const CPlusPlus::Document::Include &inc : doc->resolvedIncludes()) {
|
2016-05-11 13:02:42 +02:00
|
|
|
if (inc.resolvedFileName().endsWith(gtestH))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
2017-02-13 10:05:06 +01:00
|
|
|
for (const QString &include : snapshot.allIncludesForDocument(doc->fileName())) {
|
2016-05-11 13:02:42 +02:00
|
|
|
if (include.endsWith(gtestH))
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool hasGTestNames(const CPlusPlus::Document::Ptr &document)
|
|
|
|
|
{
|
2017-02-13 10:05:06 +01:00
|
|
|
for (const CPlusPlus::Document::MacroUse ¯o : document->macroUses()) {
|
2016-05-11 13:02:42 +02:00
|
|
|
if (!macro.isFunctionLike())
|
|
|
|
|
continue;
|
|
|
|
|
if (GTestUtils::isGTestMacro(QLatin1String(macro.macro().name()))) {
|
|
|
|
|
const QVector<CPlusPlus::Document::Block> args = macro.arguments();
|
|
|
|
|
if (args.size() != 2)
|
|
|
|
|
continue;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool handleGTest(QFutureInterface<TestParseResultPtr> futureInterface,
|
|
|
|
|
const CPlusPlus::Document::Ptr &doc,
|
2016-06-06 14:18:38 +02:00
|
|
|
const CPlusPlus::Snapshot &snapshot,
|
|
|
|
|
const Core::Id &id)
|
2016-05-11 13:02:42 +02:00
|
|
|
{
|
|
|
|
|
const CppTools::CppModelManager *modelManager = CppTools::CppModelManager::instance();
|
|
|
|
|
const QString &filePath = doc->fileName();
|
2016-06-20 07:03:55 +02:00
|
|
|
const QByteArray &fileContent = CppParser::getFileContent(filePath);
|
2016-05-11 13:02:42 +02:00
|
|
|
CPlusPlus::Document::Ptr document = snapshot.preprocessedDocument(fileContent, filePath);
|
|
|
|
|
document->check();
|
|
|
|
|
CPlusPlus::AST *ast = document->translationUnit()->ast();
|
|
|
|
|
GTestVisitor visitor(document);
|
|
|
|
|
visitor.accept(ast);
|
|
|
|
|
|
|
|
|
|
QMap<GTestCaseSpec, GTestCodeLocationList> result = visitor.gtestFunctions();
|
|
|
|
|
QString proFile;
|
|
|
|
|
const QList<CppTools::ProjectPart::Ptr> &ppList = modelManager->projectPart(filePath);
|
|
|
|
|
if (ppList.size())
|
|
|
|
|
proFile = ppList.first()->projectFile;
|
2016-07-08 12:53:57 +02:00
|
|
|
else
|
|
|
|
|
return false; // happens if shutting down while parsing
|
2016-05-11 13:02:42 +02:00
|
|
|
|
2017-02-13 10:05:06 +01:00
|
|
|
for (const GTestCaseSpec &testSpec : result.keys()) {
|
2016-06-06 14:18:38 +02:00
|
|
|
GTestParseResult *parseResult = new GTestParseResult(id);
|
2016-05-11 13:02:42 +02:00
|
|
|
parseResult->itemType = TestTreeItem::TestCase;
|
|
|
|
|
parseResult->fileName = filePath;
|
|
|
|
|
parseResult->name = testSpec.testCaseName;
|
|
|
|
|
parseResult->parameterized = testSpec.parameterized;
|
|
|
|
|
parseResult->typed = testSpec.typed;
|
|
|
|
|
parseResult->disabled = testSpec.disabled;
|
|
|
|
|
parseResult->proFile = proFile;
|
|
|
|
|
|
2017-02-13 10:05:06 +01:00
|
|
|
for (const GTestCodeLocationAndType &location : result.value(testSpec)) {
|
2016-06-06 14:18:38 +02:00
|
|
|
GTestParseResult *testSet = new GTestParseResult(id);
|
2016-05-11 13:02:42 +02:00
|
|
|
testSet->name = location.m_name;
|
|
|
|
|
testSet->fileName = filePath;
|
|
|
|
|
testSet->line = location.m_line;
|
|
|
|
|
testSet->column = location.m_column;
|
2016-06-06 12:17:19 +02:00
|
|
|
testSet->disabled = location.m_state & GTestTreeItem::Disabled;
|
2016-05-11 13:02:42 +02:00
|
|
|
testSet->itemType = location.m_type;
|
|
|
|
|
testSet->proFile = proFile;
|
|
|
|
|
|
|
|
|
|
parseResult->children.append(testSet);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
futureInterface.reportResult(TestParseResultPtr(parseResult));
|
|
|
|
|
}
|
|
|
|
|
return !result.keys().isEmpty();
|
|
|
|
|
}
|
|
|
|
|
|
2016-06-06 12:17:19 +02:00
|
|
|
bool GTestParser::processDocument(QFutureInterface<TestParseResultPtr> futureInterface,
|
|
|
|
|
const QString &fileName)
|
2016-05-11 13:02:42 +02:00
|
|
|
{
|
|
|
|
|
if (!m_cppSnapshot.contains(fileName) || !selectedForBuilding(fileName))
|
|
|
|
|
return false;
|
|
|
|
|
CPlusPlus::Document::Ptr document = m_cppSnapshot.find(fileName).value();
|
|
|
|
|
if (!includesGTest(document, m_cppSnapshot) || !hasGTestNames(document))
|
|
|
|
|
return false;
|
2016-06-06 14:18:38 +02:00
|
|
|
return handleGTest(futureInterface, document, m_cppSnapshot, id());
|
2016-05-11 13:02:42 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Internal
|
|
|
|
|
} // namespace Autotest
|