forked from qt-creator/qt-creator
AutoTest: Introduce ITestTreeItem
Preparation for having separated test tree items with a common base. Change-Id: I3735f582cc96910e971f5a41c799cc0729a10a58 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -286,7 +286,7 @@ TestConfiguration *BoostTestTreeItem::testConfiguration() const
|
||||
if (itemType == TestSuite || itemType == TestCase) {
|
||||
QStringList testCases;
|
||||
if (itemType == TestSuite) {
|
||||
forFirstLevelChildren([&testCases](TestTreeItem *child) {
|
||||
forFirstLevelChildItems([&testCases](TestTreeItem *child) {
|
||||
QTC_ASSERT(child, return);
|
||||
if (auto boostItem = static_cast<BoostTestTreeItem *>(child)) {
|
||||
if (boostItem->enabled()) {
|
||||
|
||||
@@ -89,7 +89,7 @@ TestTreeItem *CatchTreeItem::find(const TestParseResult *result)
|
||||
if (static_cast<CatchFramework *>(result->base)->grouping()) {
|
||||
const QString path = QFileInfo(result->fileName).absolutePath();
|
||||
for (int row = 0; row < childCount(); ++row) {
|
||||
TestTreeItem *group = childAt(row);
|
||||
TestTreeItem *group = childItem(row);
|
||||
if (group->filePath() != path)
|
||||
continue;
|
||||
if (auto groupChild = group->findChildByFile(result->fileName))
|
||||
@@ -192,7 +192,7 @@ static void collectTestInfo(const TestTreeItem *item,
|
||||
QTC_ASSERT(item, return);
|
||||
const int childCount = item->childCount();
|
||||
if (item->type() == TestTreeItem::GroupNode) {
|
||||
item->forFirstLevelChildren([&testCasesForProfile, ignoreCheckState](TestTreeItem *it) {
|
||||
item->forFirstLevelChildItems([&testCasesForProfile, ignoreCheckState](TestTreeItem *it) {
|
||||
collectTestInfo(it, testCasesForProfile, ignoreCheckState);
|
||||
});
|
||||
return;
|
||||
@@ -201,14 +201,14 @@ static void collectTestInfo(const TestTreeItem *item,
|
||||
QTC_ASSERT(childCount != 0, return);
|
||||
QTC_ASSERT(item->type() == TestTreeItem::TestSuite, return);
|
||||
if (ignoreCheckState || item->checked() == Qt::Checked) {
|
||||
const QString &projectFile = item->childAt(0)->proFile();
|
||||
item->forAllChildren([&testCasesForProfile, &projectFile](TestTreeItem *it) {
|
||||
const QString &projectFile = item->childItem(0)->proFile();
|
||||
item->forAllChildItems([&testCasesForProfile, &projectFile](TestTreeItem *it) {
|
||||
CatchTreeItem *current = static_cast<CatchTreeItem *>(it);
|
||||
testCasesForProfile[projectFile].names.append(current->testCasesString());
|
||||
});
|
||||
testCasesForProfile[projectFile].internalTargets.unite(item->internalTargets());
|
||||
} else if (item->checked() == Qt::PartiallyChecked) {
|
||||
item->forFirstLevelChildren([&testCasesForProfile](TestTreeItem *child) {
|
||||
item->forFirstLevelChildItems([&testCasesForProfile](TestTreeItem *child) {
|
||||
QTC_ASSERT(child->type() == TestTreeItem::TestCase, return);
|
||||
if (child->checked() == Qt::Checked) {
|
||||
CatchTreeItem *current = static_cast<CatchTreeItem *>(child);
|
||||
@@ -227,7 +227,7 @@ static void collectFailedTestInfo(const CatchTreeItem *item,
|
||||
QTC_ASSERT(item, return);
|
||||
QTC_ASSERT(item->type() == TestTreeItem::Root, return);
|
||||
|
||||
item->forAllChildren([&testCasesForProfile](TestTreeItem *it) {
|
||||
item->forAllChildItems([&testCasesForProfile](TestTreeItem *it) {
|
||||
QTC_ASSERT(it, return);
|
||||
CatchTreeItem *parent = static_cast<CatchTreeItem *>(it->parentItem());
|
||||
QTC_ASSERT(parent, return);
|
||||
@@ -283,7 +283,7 @@ QList<TestConfiguration *> CatchTreeItem::getTestConfigurationsForFile(const Uti
|
||||
|
||||
const QString filePath = fileName.toString();
|
||||
for (int row = 0, count = childCount(); row < count; ++row) {
|
||||
const TestTreeItem *item = childAt(row);
|
||||
const TestTreeItem *item = childItem(row);
|
||||
QTC_ASSERT(item, continue);
|
||||
|
||||
if (childAt(row)->name() != filePath)
|
||||
@@ -292,7 +292,7 @@ QList<TestConfiguration *> CatchTreeItem::getTestConfigurationsForFile(const Uti
|
||||
CatchConfiguration *testConfig = nullptr;
|
||||
QStringList testCases;
|
||||
|
||||
item->forFirstLevelChildren([&testCases](TestTreeItem *child) {
|
||||
item->forFirstLevelChildItems([&testCases](TestTreeItem *child) {
|
||||
CatchTreeItem *current = static_cast<CatchTreeItem *>(child);
|
||||
testCases << current->testCasesString();
|
||||
});
|
||||
@@ -326,9 +326,8 @@ QList<TestConfiguration *> CatchTreeItem::getTestConfigurations(bool ignoreCheck
|
||||
return result;
|
||||
|
||||
QHash<QString, CatchTestCases> testCasesForProfile;
|
||||
forFirstLevelChildren([&testCasesForProfile, ignoreCheckState](TestTreeItem *item) {
|
||||
collectTestInfo(item, testCasesForProfile, ignoreCheckState);
|
||||
});
|
||||
for (int row = 0, end = childCount(); row < end; ++row)
|
||||
collectTestInfo(childItem(row), testCasesForProfile, ignoreCheckState);
|
||||
|
||||
for (auto it = testCasesForProfile.begin(), end = testCasesForProfile.end(); it != end; ++it) {
|
||||
for (const QString &target : qAsConst(it.value().internalTargets)) {
|
||||
|
||||
@@ -230,13 +230,13 @@ static void collectTestInfo(const GTestTreeItem *item,
|
||||
QTC_ASSERT(childCount != 0, return);
|
||||
QTC_ASSERT(item->type() == TestTreeItem::TestSuite, return);
|
||||
if (ignoreCheckState || item->checked() == Qt::Checked) {
|
||||
const QString &projectFile = item->childAt(0)->proFile();
|
||||
const QString &projectFile = item->childItem(0)->proFile();
|
||||
testCasesForProFile[projectFile].filters.append(
|
||||
gtestFilter(item->state()).arg(item->name()).arg('*'));
|
||||
testCasesForProFile[projectFile].testSetCount += childCount - 1;
|
||||
testCasesForProFile[projectFile].internalTargets.unite(item->internalTargets());
|
||||
} else if (item->checked() == Qt::PartiallyChecked) {
|
||||
item->forFirstLevelChildren([&testCasesForProFile, item](TestTreeItem *child){
|
||||
item->forFirstLevelChildItems([&testCasesForProFile, item](TestTreeItem *child){
|
||||
QTC_ASSERT(child->type() == TestTreeItem::TestCase, return);
|
||||
if (child->checked() == Qt::Checked) {
|
||||
testCasesForProFile[child->proFile()].filters.append(
|
||||
@@ -254,7 +254,7 @@ static void collectFailedTestInfo(const GTestTreeItem *item,
|
||||
QTC_ASSERT(item, return);
|
||||
QTC_ASSERT(item->type() == TestTreeItem::Root, return);
|
||||
|
||||
item->forAllChildren([&testCasesForProfile](TestTreeItem *it) {
|
||||
item->forAllChildItems([&testCasesForProfile](TestTreeItem *it) {
|
||||
QTC_ASSERT(it, return);
|
||||
GTestTreeItem *parent = static_cast<GTestTreeItem *>(it->parentItem());
|
||||
QTC_ASSERT(parent, return);
|
||||
@@ -340,7 +340,7 @@ QList<TestConfiguration *> GTestTreeItem::getTestConfigurationsForFile(const Uti
|
||||
|
||||
QHash<QString, GTestCases> testCases;
|
||||
const QString &file = fileName.toString();
|
||||
forAllChildren([&testCases, &file](TestTreeItem *node) {
|
||||
forAllChildItems([&testCases, &file](TestTreeItem *node) {
|
||||
if (node->type() == Type::TestCase && node->filePath() == file) {
|
||||
QTC_ASSERT(node->parentItem(), return);
|
||||
const GTestTreeItem *testCase = static_cast<GTestTreeItem *>(node->parentItem());
|
||||
@@ -469,7 +469,7 @@ TestTreeItem *GTestTreeItem::createParentGroupNode() const
|
||||
return new GTestTreeItem(framework(), base.baseName(), fileInfo.absolutePath(), TestTreeItem::GroupNode);
|
||||
} else { // GTestFilter
|
||||
QTC_ASSERT(childCount(), return nullptr); // paranoia
|
||||
const TestTreeItem *firstChild = childAt(0);
|
||||
const TestTreeItem *firstChild = childItem(0);
|
||||
const QString activeFilter = GTestFramework::currentGTestFilter();
|
||||
const QString fullTestName = name() + '.' + firstChild->name();
|
||||
const QString groupNodeName =
|
||||
@@ -497,7 +497,7 @@ TestTreeItem *GTestTreeItem::findChildByNameStateAndFile(const QString &name,
|
||||
GTestTreeItem::TestStates state,
|
||||
const QString &proFile) const
|
||||
{
|
||||
return findFirstLevelChild([name, state, proFile](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([name, state, proFile](const TestTreeItem *other) {
|
||||
const GTestTreeItem *gtestItem = static_cast<const GTestTreeItem *>(other);
|
||||
return other->proFile() == proFile && other->name() == name && gtestItem->state() == state;
|
||||
});
|
||||
|
||||
@@ -38,7 +38,7 @@ template<class T>
|
||||
class ItemDataCache
|
||||
{
|
||||
public:
|
||||
void insert(TestTreeItem *item, const T &value) { m_cache[item->cacheName()] = {0, value}; }
|
||||
void insert(ITestTreeItem *item, const T &value) { m_cache[item->cacheName()] = {0, value}; }
|
||||
void evolve()
|
||||
{
|
||||
auto it = m_cache.begin(), end = m_cache.end();
|
||||
@@ -46,7 +46,7 @@ public:
|
||||
it = it->generation++ >= maxGen ? m_cache.erase(it) : ++it;
|
||||
}
|
||||
|
||||
Utils::optional<T> get(TestTreeItem *item)
|
||||
Utils::optional<T> get(ITestTreeItem *item)
|
||||
{
|
||||
auto entry = m_cache.find(item->cacheName());
|
||||
if (entry == m_cache.end())
|
||||
|
||||
@@ -53,10 +53,10 @@ QHash<QString, QString> testCaseNamesForFiles(ITestFramework *framework, const Q
|
||||
TestTreeItem *rootNode = framework->rootNode();
|
||||
QTC_ASSERT(rootNode, return result);
|
||||
|
||||
rootNode->forFirstLevelChildren([&result, &files](TestTreeItem *child) {
|
||||
rootNode->forFirstLevelChildren([&result, &files](ITestTreeItem *child) {
|
||||
if (files.contains(child->filePath()))
|
||||
result.insert(child->filePath(), child->name());
|
||||
child->forFirstLevelChildren([&result, &files, child](TestTreeItem *grandChild) {
|
||||
child->forFirstLevelChildren([&result, &files, child](ITestTreeItem *grandChild) {
|
||||
if (files.contains(grandChild->filePath()))
|
||||
result.insert(grandChild->filePath(), child->name());
|
||||
});
|
||||
@@ -70,7 +70,7 @@ QMultiHash<QString, QString> alternativeFiles(ITestFramework *framework, const Q
|
||||
TestTreeItem *rootNode = framework->rootNode();
|
||||
QTC_ASSERT(rootNode, return result);
|
||||
|
||||
rootNode->forFirstLevelChildren([&result, &files](TestTreeItem *child) {
|
||||
rootNode->forFirstLevelChildren([&result, &files](ITestTreeItem *child) {
|
||||
const QString &baseFilePath = child->filePath();
|
||||
for (int childRow = 0, count = child->childCount(); childRow < count; ++childRow) {
|
||||
auto grandChild = static_cast<const QtTestTreeItem *>(child->childAt(childRow));
|
||||
|
||||
@@ -154,7 +154,7 @@ static void fillTestConfigurationsFromCheckState(const TestTreeItem *item,
|
||||
QTC_ASSERT(item, return);
|
||||
if (item->type() == TestTreeItem::GroupNode) {
|
||||
for (int row = 0, count = item->childCount(); row < count; ++row)
|
||||
fillTestConfigurationsFromCheckState(item->childAt(row), testConfigurations);
|
||||
fillTestConfigurationsFromCheckState(item->childItem(row), testConfigurations);
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(item->type() == TestTreeItem::TestCase, return);
|
||||
@@ -169,12 +169,12 @@ static void fillTestConfigurationsFromCheckState(const TestTreeItem *item,
|
||||
return;
|
||||
case Qt::PartiallyChecked:
|
||||
QStringList testCases;
|
||||
item->forFirstLevelChildren([&testCases](TestTreeItem *grandChild) {
|
||||
item->forFirstLevelChildren([&testCases](ITestTreeItem *grandChild) {
|
||||
if (grandChild->checked() == Qt::Checked) {
|
||||
testCases << grandChild->name();
|
||||
} else if (grandChild->checked() == Qt::PartiallyChecked) {
|
||||
const QString funcName = grandChild->name();
|
||||
grandChild->forFirstLevelChildren([&testCases, &funcName](TestTreeItem *dataTag) {
|
||||
grandChild->forFirstLevelChildren([&testCases, &funcName](ITestTreeItem *dataTag) {
|
||||
if (dataTag->checked() == Qt::Checked)
|
||||
testCases << funcName + ':' + dataTag->name();
|
||||
});
|
||||
@@ -195,16 +195,16 @@ static void collectFailedTestInfo(TestTreeItem *item, QList<TestConfiguration *>
|
||||
QTC_ASSERT(item, return);
|
||||
if (item->type() == TestTreeItem::GroupNode) {
|
||||
for (int row = 0, count = item->childCount(); row < count; ++row)
|
||||
collectFailedTestInfo(item->childAt(row), testConfigs);
|
||||
collectFailedTestInfo(item->childItem(row), testConfigs);
|
||||
return;
|
||||
}
|
||||
QTC_ASSERT(item->type() == TestTreeItem::TestCase, return);
|
||||
QStringList testCases;
|
||||
item->forFirstLevelChildren([&testCases](TestTreeItem *func) {
|
||||
item->forFirstLevelChildren([&testCases](ITestTreeItem *func) {
|
||||
if (func->data(0, FailedRole).toBool()) {
|
||||
testCases << func->name();
|
||||
} else {
|
||||
func->forFirstLevelChildren([&testCases, func](TestTreeItem *dataTag) {
|
||||
func->forFirstLevelChildren([&testCases, func](ITestTreeItem *dataTag) {
|
||||
if (dataTag->data(0, FailedRole).toBool())
|
||||
testCases << func->name() + ':' + dataTag->name();
|
||||
});
|
||||
@@ -237,13 +237,13 @@ QList<TestConfiguration *> QtTestTreeItem::getAllTestConfigurations() const
|
||||
if (!project || type() != Root)
|
||||
return result;
|
||||
|
||||
forFirstLevelChildren([&result](TestTreeItem *child) {
|
||||
forFirstLevelChildren([&result](ITestTreeItem *child) {
|
||||
if (child->type() == TestCase) {
|
||||
TestConfiguration *tc = child->testConfiguration();
|
||||
QTC_ASSERT(tc, return);
|
||||
result << tc;
|
||||
} else if (child->type() == GroupNode) {
|
||||
child->forFirstLevelChildren([&result](TestTreeItem *groupChild) {
|
||||
child->forFirstLevelChildren([&result](ITestTreeItem *groupChild) {
|
||||
TestConfiguration *tc = groupChild->testConfiguration();
|
||||
QTC_ASSERT(tc, return);
|
||||
result << tc;
|
||||
@@ -261,7 +261,7 @@ QList<TestConfiguration *> QtTestTreeItem::getSelectedTestConfigurations() const
|
||||
return result;
|
||||
|
||||
for (int row = 0, count = childCount(); row < count; ++row)
|
||||
fillTestConfigurationsFromCheckState(childAt(row), result);
|
||||
fillTestConfigurationsFromCheckState(childItem(row), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -270,9 +270,8 @@ QList<TestConfiguration *> QtTestTreeItem::getFailedTestConfigurations() const
|
||||
{
|
||||
QList<TestConfiguration *> result;
|
||||
QTC_ASSERT(type() == TestTreeItem::Root, return result);
|
||||
forFirstLevelChildren([&result](TestTreeItem *child) {
|
||||
collectFailedTestInfo(child, result);
|
||||
});
|
||||
for (int row = 0, end = childCount(); row < end; ++row)
|
||||
collectFailedTestInfo(childItem(row), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -286,7 +285,7 @@ QList<TestConfiguration *> QtTestTreeItem::getTestConfigurationsForFile(const Ut
|
||||
|
||||
QHash<TestTreeItem *, QStringList> testFunctions;
|
||||
const QString &file = fileName.toString();
|
||||
forAllChildren([&testFunctions, &file](TestTreeItem *node) {
|
||||
forAllChildItems([&testFunctions, &file](TestTreeItem *node) {
|
||||
if (node->type() == Type::TestFunction && node->filePath() == file) {
|
||||
QTC_ASSERT(node->parentItem(), return);
|
||||
TestTreeItem *testCase = node->parentItem();
|
||||
@@ -314,7 +313,7 @@ TestTreeItem *QtTestTreeItem::find(const TestParseResult *result)
|
||||
if (static_cast<QtTestFramework *>(result->base)->grouping()) {
|
||||
const QString path = QFileInfo(result->fileName).absolutePath();
|
||||
for (int row = 0; row < childCount(); ++row) {
|
||||
TestTreeItem *group = childAt(row);
|
||||
TestTreeItem *group = childItem(row);
|
||||
if (group->filePath() != path)
|
||||
continue;
|
||||
if (auto groupChild = group->findChildByFile(result->fileName))
|
||||
@@ -394,7 +393,7 @@ bool QtTestTreeItem::isGroupable() const
|
||||
|
||||
TestTreeItem *QtTestTreeItem::findChildByNameAndInheritance(const QString &name, bool inherited) const
|
||||
{
|
||||
return findFirstLevelChild([name, inherited](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([name, inherited](const TestTreeItem *other) {
|
||||
const QtTestTreeItem *qtOther = static_cast<const QtTestTreeItem *>(other);
|
||||
return qtOther->inherited() == inherited && qtOther->name() == name;
|
||||
});
|
||||
|
||||
@@ -52,14 +52,14 @@ QHash<QString, QString> proFilesForQmlFiles(ITestFramework *framework, const QSt
|
||||
if (files.isEmpty())
|
||||
return result;
|
||||
|
||||
rootNode->forFirstLevelChildren([&result, &files](TestTreeItem *child) {
|
||||
rootNode->forFirstLevelChildItems([&result, &files](TestTreeItem *child) {
|
||||
const QString &file = child->filePath();
|
||||
if (!file.isEmpty() && files.contains(file)) {
|
||||
const QString &proFile = child->proFile();
|
||||
if (!proFile.isEmpty())
|
||||
result.insert(file, proFile);
|
||||
}
|
||||
child->forFirstLevelChildren([&result, &files](TestTreeItem *grandChild) {
|
||||
child->forFirstLevelChildItems([&result, &files](TestTreeItem *grandChild) {
|
||||
const QString &file = grandChild->filePath();
|
||||
if (!file.isEmpty() && files.contains(file)) {
|
||||
const QString &proFile = grandChild->proFile();
|
||||
|
||||
@@ -133,7 +133,7 @@ TestConfiguration *QuickTestTreeItem::testConfiguration() const
|
||||
case TestCase: {
|
||||
const QString testName = name();
|
||||
QStringList testFunctions;
|
||||
forFirstLevelChildren([&testFunctions, &testName](TestTreeItem *child) {
|
||||
forFirstLevelChildren([&testFunctions, &testName](ITestTreeItem *child) {
|
||||
if (child->type() == TestTreeItem::TestFunction)
|
||||
testFunctions << testName + "::" + child->name();
|
||||
});
|
||||
@@ -177,7 +177,7 @@ static QList<TestConfiguration *> testConfigurationsFor(
|
||||
const QString name = treeItem->name();
|
||||
|
||||
QStringList functions;
|
||||
treeItem->forFirstLevelChildren([&functions, &name, &predicate](TestTreeItem *child) {
|
||||
treeItem->forFirstLevelChildItems([&functions, &name, &predicate](TestTreeItem *child) {
|
||||
if (predicate(child))
|
||||
functions << name + "::" + child->name();
|
||||
});
|
||||
@@ -228,10 +228,10 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
|
||||
return result;
|
||||
|
||||
QHash<QString, Tests> testsForProfile;
|
||||
forFirstLevelChildren([&testsForProfile](TestTreeItem *child) {
|
||||
forFirstLevelChildItems([&testsForProfile](TestTreeItem *child) {
|
||||
// unnamed Quick Tests must be handled separately
|
||||
if (child->name().isEmpty()) {
|
||||
child->forFirstLevelChildren([&testsForProfile](TestTreeItem *grandChild) {
|
||||
child->forFirstLevelChildItems([&testsForProfile](TestTreeItem *grandChild) {
|
||||
const QString &proFile = grandChild->proFile();
|
||||
++(testsForProfile[proFile].testCount);
|
||||
testsForProfile[proFile].internalTargets = grandChild->internalTargets();
|
||||
@@ -242,7 +242,7 @@ QList<TestConfiguration *> QuickTestTreeItem::getAllTestConfigurations() const
|
||||
if (child->type() == TestCase) {
|
||||
addTestsForItem(testsForProfile[child->proFile()], child);
|
||||
} else if (child->type() == GroupNode) {
|
||||
child->forFirstLevelChildren([&testsForProfile](TestTreeItem *grandChild) {
|
||||
child->forFirstLevelChildItems([&testsForProfile](TestTreeItem *grandChild) {
|
||||
addTestsForItem(testsForProfile[grandChild->proFile()], grandChild);
|
||||
});
|
||||
}
|
||||
@@ -292,7 +292,7 @@ TestTreeItem *QuickTestTreeItem::find(const TestParseResult *result)
|
||||
return unnamedQuickTests();
|
||||
if (static_cast<QuickTestFramework *>(result->base)->grouping()) {
|
||||
const QString path = QFileInfo(result->fileName).absolutePath();
|
||||
TestTreeItem *group = findFirstLevelChild([path](TestTreeItem *group) {
|
||||
TestTreeItem *group = findFirstLevelChildItem([path](TestTreeItem *group) {
|
||||
return group->filePath() == path;
|
||||
});
|
||||
return group ? group->findChildByNameAndFile(result->name, result->fileName) : nullptr;
|
||||
@@ -348,14 +348,14 @@ bool QuickTestTreeItem::modify(const TestParseResult *result)
|
||||
}
|
||||
}
|
||||
|
||||
bool QuickTestTreeItem::lessThan(const TestTreeItem *other, TestTreeItem::SortMode mode) const
|
||||
bool QuickTestTreeItem::lessThan(const ITestTreeItem *other, TestTreeItem::SortMode mode) const
|
||||
{
|
||||
// handle special item (<unnamed>)
|
||||
if (name().isEmpty())
|
||||
return false;
|
||||
if (other->name().isEmpty())
|
||||
return true;
|
||||
return TestTreeItem::lessThan(other, mode);
|
||||
return ITestTreeItem::lessThan(other, mode);
|
||||
}
|
||||
|
||||
bool QuickTestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
|
||||
@@ -405,7 +405,7 @@ void QuickTestTreeItem::markForRemovalRecursively(const QString &filePath)
|
||||
const QString proFile = parser->projectFileForMainCppFile(filePath);
|
||||
if (!proFile.isEmpty()) {
|
||||
TestTreeItem *root = framework()->rootNode();
|
||||
root->forAllChildren([proFile](TestTreeItem *it) {
|
||||
root->forAllChildItems([proFile](TestTreeItem *it) {
|
||||
if (it->proFile() == proFile)
|
||||
it->markForRemoval(true);
|
||||
});
|
||||
@@ -417,7 +417,7 @@ TestTreeItem *QuickTestTreeItem::findChildByFileNameAndType(const QString &fileP
|
||||
TestTreeItem::Type tType)
|
||||
|
||||
{
|
||||
return findFirstLevelChild([filePath, name, tType](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([filePath, name, tType](const TestTreeItem *other) {
|
||||
return other->type() == tType && other->name() == name && other->filePath() == filePath;
|
||||
});
|
||||
}
|
||||
@@ -425,7 +425,7 @@ TestTreeItem *QuickTestTreeItem::findChildByFileNameAndType(const QString &fileP
|
||||
TestTreeItem *QuickTestTreeItem::findChildByNameFileAndLine(const QString &name,
|
||||
const QString &filePath, int line)
|
||||
{
|
||||
return findFirstLevelChild([name, filePath, line](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([name, filePath, line](const TestTreeItem *other) {
|
||||
return other->filePath() == filePath && other->line() == line && other->name() == name;
|
||||
});
|
||||
}
|
||||
@@ -435,7 +435,7 @@ TestTreeItem *QuickTestTreeItem::unnamedQuickTests() const
|
||||
if (type() != Root)
|
||||
return nullptr;
|
||||
|
||||
return findFirstLevelChild([](TestTreeItem *child) { return child->name().isEmpty(); });
|
||||
return findFirstLevelChildItem([](TestTreeItem *child) { return child->name().isEmpty(); });
|
||||
}
|
||||
|
||||
} // namespace Internal
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
TestTreeItem *find(const TestParseResult *result) override;
|
||||
TestTreeItem *findChild(const TestTreeItem *other) override;
|
||||
bool modify(const TestParseResult *result) override;
|
||||
bool lessThan(const TestTreeItem *other, SortMode mode) const override;
|
||||
bool lessThan(const ITestTreeItem *other, SortMode mode) const override;
|
||||
bool isGroupNodeFor(const TestTreeItem *other) const override;
|
||||
bool removeOnSweepIfEmpty() const override;
|
||||
TestTreeItem *createParentGroupNode() const override;
|
||||
|
||||
@@ -242,7 +242,7 @@ void TestNavigationWidget::updateExpandedStateCache()
|
||||
|
||||
for (Utils::TreeItem *rootNode : *m_model->rootItem()) {
|
||||
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
||||
m_expandedStateCache.insert(static_cast<TestTreeItem *>(child),
|
||||
m_expandedStateCache.insert(static_cast<ITestTreeItem *>(child),
|
||||
m_view->isExpanded(child->index()));
|
||||
});
|
||||
}
|
||||
@@ -322,7 +322,7 @@ void TestNavigationWidget::reapplyCachedExpandedState()
|
||||
using namespace Utils;
|
||||
for (TreeItem *rootNode : *m_model->rootItem()) {
|
||||
rootNode->forAllChildren([this](TreeItem *child) {
|
||||
optional<bool> cached = m_expandedStateCache.get(static_cast<TestTreeItem *>(child));
|
||||
optional<bool> cached = m_expandedStateCache.get(static_cast<ITestTreeItem *>(child));
|
||||
if (cached.has_value()) {
|
||||
QModelIndex index = child->index();
|
||||
if (m_view->isExpanded(index) != cached.value())
|
||||
|
||||
@@ -40,27 +40,6 @@
|
||||
|
||||
namespace Autotest {
|
||||
|
||||
TestTreeItem::TestTreeItem(ITestBase *testBase, const QString &name,
|
||||
const QString &filePath, Type type)
|
||||
: m_testBase(testBase),
|
||||
m_name(name),
|
||||
m_filePath(filePath),
|
||||
m_type(type)
|
||||
{
|
||||
switch (m_type) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestSuite:
|
||||
case TestCase:
|
||||
case TestFunction:
|
||||
m_checked = Qt::Checked;
|
||||
break;
|
||||
default:
|
||||
m_checked = Qt::Unchecked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static QIcon testTreeIcon(TestTreeItem::Type type)
|
||||
{
|
||||
static QIcon icons[] = {
|
||||
@@ -77,7 +56,15 @@ static QIcon testTreeIcon(TestTreeItem::Type type)
|
||||
return icons[type];
|
||||
}
|
||||
|
||||
QVariant TestTreeItem::data(int /*column*/, int role) const
|
||||
ITestTreeItem::ITestTreeItem(ITestBase *testBase, const QString &name,
|
||||
const QString &filePath, Type type)
|
||||
: m_testBase(testBase)
|
||||
, m_name(name)
|
||||
, m_filePath(filePath)
|
||||
, m_type(type)
|
||||
{}
|
||||
|
||||
QVariant ITestTreeItem::data(int /*column*/, int role) const
|
||||
{
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
@@ -91,13 +78,6 @@ QVariant TestTreeItem::data(int /*column*/, int role) const
|
||||
return testTreeIcon(m_type);
|
||||
case Qt::CheckStateRole:
|
||||
return QVariant();
|
||||
case LinkRole: {
|
||||
if (m_type == GroupNode)
|
||||
return QVariant();
|
||||
QVariant itemLink;
|
||||
itemLink.setValue(Utils::Link(m_filePath, int(m_line), int(m_column)));
|
||||
return itemLink;
|
||||
}
|
||||
case ItalicRole:
|
||||
return false;
|
||||
case TypeRole:
|
||||
@@ -110,7 +90,7 @@ QVariant TestTreeItem::data(int /*column*/, int role) const
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role)
|
||||
bool ITestTreeItem::setData(int /*column*/, const QVariant &data, int role)
|
||||
{
|
||||
if (role == Qt::CheckStateRole) {
|
||||
Qt::CheckState old = m_checked;
|
||||
@@ -122,10 +102,10 @@ bool TestTreeItem::setData(int /*column*/, const QVariant &data, int role)
|
||||
return false;
|
||||
}
|
||||
|
||||
Qt::ItemFlags TestTreeItem::flags(int /*column*/) const
|
||||
Qt::ItemFlags ITestTreeItem::flags(int /*column*/) const
|
||||
{
|
||||
static const Qt::ItemFlags defaultFlags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
switch (m_type) {
|
||||
switch (type()) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsAutoTristate | Qt::ItemIsUserCheckable;
|
||||
@@ -139,6 +119,70 @@ Qt::ItemFlags TestTreeItem::flags(int /*column*/) const
|
||||
}
|
||||
}
|
||||
|
||||
Qt::CheckState ITestTreeItem::checked() const
|
||||
{
|
||||
return m_checked;
|
||||
}
|
||||
|
||||
bool ITestTreeItem::lessThan(const ITestTreeItem *other, ITestTreeItem::SortMode mode) const
|
||||
{
|
||||
const QString &lhs = data(0, Qt::DisplayRole).toString();
|
||||
const QString &rhs = other->data(0, Qt::DisplayRole).toString();
|
||||
|
||||
switch (mode) {
|
||||
case Alphabetically:
|
||||
if (lhs == rhs)
|
||||
return index().row() > other->index().row();
|
||||
return lhs > rhs;
|
||||
case Naturally: {
|
||||
if (type() == GroupNode && other->type() == GroupNode)
|
||||
return filePath() > other->filePath();
|
||||
|
||||
const Utils::Link &leftLink = data(0, LinkRole).value<Utils::Link>();
|
||||
const Utils::Link &rightLink = other->data(0, LinkRole).value<Utils::Link>();
|
||||
if (leftLink.targetFileName == rightLink.targetFileName) {
|
||||
return leftLink.targetLine == rightLink.targetLine
|
||||
? leftLink.targetColumn > rightLink.targetColumn
|
||||
: leftLink.targetLine > rightLink.targetLine;
|
||||
}
|
||||
return leftLink.targetFileName > rightLink.targetFileName;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/****************************** TestTreeItem ********************************************/
|
||||
|
||||
TestTreeItem::TestTreeItem(ITestBase *testBase, const QString &name,
|
||||
const QString &filePath, Type type)
|
||||
: ITestTreeItem(testBase, name, filePath, type)
|
||||
{
|
||||
switch (type) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestSuite:
|
||||
case TestCase:
|
||||
case TestFunction:
|
||||
m_checked = Qt::Checked;
|
||||
break;
|
||||
default:
|
||||
m_checked = Qt::Unchecked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant TestTreeItem::data(int column, int role) const
|
||||
{
|
||||
if (role == LinkRole) {
|
||||
if (type() == GroupNode)
|
||||
return QVariant();
|
||||
QVariant itemLink;
|
||||
itemLink.setValue(Utils::Link(filePath(), line(), int(m_column)));
|
||||
return itemLink;
|
||||
}
|
||||
return ITestTreeItem::data(column, role);
|
||||
}
|
||||
|
||||
bool TestTreeItem::modifyTestCaseOrSuiteContent(const TestParseResult *result)
|
||||
{
|
||||
bool hasBeenModified = modifyName(result->name);
|
||||
@@ -164,8 +208,8 @@ bool TestTreeItem::modifyDataTagContent(const TestParseResult *result)
|
||||
bool TestTreeItem::modifyLineAndColumn(const TestParseResult *result)
|
||||
{
|
||||
bool hasBeenModified = false;
|
||||
if (m_line != result->line) {
|
||||
m_line = result->line;
|
||||
if (line() != result->line) {
|
||||
setLine(result->line);
|
||||
hasBeenModified = true;
|
||||
}
|
||||
if (m_column != result->column) {
|
||||
@@ -175,21 +219,6 @@ bool TestTreeItem::modifyLineAndColumn(const TestParseResult *result)
|
||||
return hasBeenModified;
|
||||
}
|
||||
|
||||
Qt::CheckState TestTreeItem::checked() const
|
||||
{
|
||||
switch (m_type) {
|
||||
case Root:
|
||||
case GroupNode:
|
||||
case TestSuite:
|
||||
case TestCase:
|
||||
case TestFunction:
|
||||
case TestDataTag:
|
||||
return m_checked;
|
||||
default:
|
||||
return Qt::Unchecked;
|
||||
}
|
||||
}
|
||||
|
||||
void TestTreeItem::markForRemoval(bool mark)
|
||||
{
|
||||
m_status = mark ? MarkedForRemoval : Cleared;
|
||||
@@ -199,19 +228,24 @@ void TestTreeItem::markForRemovalRecursively(bool mark)
|
||||
{
|
||||
markForRemoval(mark);
|
||||
for (int row = 0, count = childCount(); row < count; ++row)
|
||||
childAt(row)->markForRemovalRecursively(mark);
|
||||
childItem(row)->markForRemovalRecursively(mark);
|
||||
}
|
||||
|
||||
void TestTreeItem::markForRemovalRecursively(const QString &filePath)
|
||||
void TestTreeItem::markForRemovalRecursively(const QString &filepath)
|
||||
{
|
||||
bool mark = m_filePath == filePath;
|
||||
forFirstLevelChildren([&mark, &filePath](TestTreeItem *child) {
|
||||
child->markForRemovalRecursively(filePath);
|
||||
bool mark = filePath() == filepath;
|
||||
forFirstLevelChildItems([&mark, &filepath](TestTreeItem *child) {
|
||||
child->markForRemovalRecursively(filepath);
|
||||
mark &= child->markedForRemoval();
|
||||
});
|
||||
markForRemoval(mark);
|
||||
}
|
||||
|
||||
TestTreeItem *TestTreeItem::childItem(int at) const
|
||||
{
|
||||
return static_cast<TestTreeItem *>(childAt(at));
|
||||
}
|
||||
|
||||
TestTreeItem *TestTreeItem::parentItem() const
|
||||
{
|
||||
return static_cast<TestTreeItem *>(parent());
|
||||
@@ -219,26 +253,27 @@ TestTreeItem *TestTreeItem::parentItem() const
|
||||
|
||||
TestTreeItem *TestTreeItem::findChildByName(const QString &name)
|
||||
{
|
||||
return findFirstLevelChild([name](const TestTreeItem *other) { return other->name() == name; });
|
||||
return findFirstLevelChildItem([name](const TestTreeItem *other) {
|
||||
return other->name() == name;
|
||||
});
|
||||
}
|
||||
|
||||
TestTreeItem *TestTreeItem::findChildByFile(const QString &filePath)
|
||||
{
|
||||
return findFirstLevelChild([filePath](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([filePath](const TestTreeItem *other) {
|
||||
return other->filePath() == filePath;
|
||||
});
|
||||
}
|
||||
|
||||
TestTreeItem *TestTreeItem::findChildByFileAndType(const QString &filePath, Type tType)
|
||||
{
|
||||
return findFirstLevelChild([filePath, tType](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([filePath, tType](const TestTreeItem *other) {
|
||||
return other->type() == tType && other->filePath() == filePath;
|
||||
});
|
||||
}
|
||||
});}
|
||||
|
||||
TestTreeItem *TestTreeItem::findChildByNameAndFile(const QString &name, const QString &filePath)
|
||||
{
|
||||
return findFirstLevelChild([name, filePath](const TestTreeItem *other) {
|
||||
return findFirstLevelChildItem([name, filePath](const TestTreeItem *other) {
|
||||
return other->filePath() == filePath && other->name() == name;
|
||||
});
|
||||
}
|
||||
@@ -258,53 +293,11 @@ TestConfiguration *TestTreeItem::asConfiguration(TestRunMode mode) const
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> TestTreeItem::getAllTestConfigurations() const
|
||||
{
|
||||
return QList<TestConfiguration *>();
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> TestTreeItem::getSelectedTestConfigurations() const
|
||||
{
|
||||
return QList<TestConfiguration *>();
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> TestTreeItem::getFailedTestConfigurations() const
|
||||
{
|
||||
return QList<TestConfiguration *>();
|
||||
}
|
||||
|
||||
QList<TestConfiguration *> TestTreeItem::getTestConfigurationsForFile(const Utils::FilePath &) const
|
||||
{
|
||||
return QList<TestConfiguration *>();
|
||||
}
|
||||
|
||||
bool TestTreeItem::lessThan(const TestTreeItem *other, SortMode mode) const
|
||||
{
|
||||
const QString &lhs = data(0, Qt::DisplayRole).toString();
|
||||
const QString &rhs = other->data(0, Qt::DisplayRole).toString();
|
||||
|
||||
switch (mode) {
|
||||
case Alphabetically:
|
||||
if (lhs == rhs)
|
||||
return index().row() > other->index().row();
|
||||
return lhs > rhs;
|
||||
case Naturally: {
|
||||
if (m_type == GroupNode && other->type() == GroupNode)
|
||||
return m_filePath > other->filePath();
|
||||
|
||||
const Utils::Link &leftLink = data(0, LinkRole).value<Utils::Link>();
|
||||
const Utils::Link &rightLink = other->data(0, LinkRole).value<Utils::Link>();
|
||||
if (leftLink.targetFileName == rightLink.targetFileName) {
|
||||
return leftLink.targetLine == rightLink.targetLine
|
||||
? leftLink.targetColumn > rightLink.targetColumn
|
||||
: leftLink.targetLine > rightLink.targetLine;
|
||||
}
|
||||
return leftLink.targetFileName > rightLink.targetFileName;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestTreeItem::isGroupNodeFor(const TestTreeItem *other) const
|
||||
{
|
||||
QTC_ASSERT(other, return false);
|
||||
@@ -323,47 +316,74 @@ bool TestTreeItem::isGroupable() const
|
||||
QSet<QString> TestTreeItem::internalTargets() const
|
||||
{
|
||||
auto cppMM = CppTools::CppModelManager::instance();
|
||||
const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(m_filePath);
|
||||
const QList<CppTools::ProjectPart::Ptr> projectParts = cppMM->projectPart(filePath());
|
||||
// if we have no project parts it's most likely a header with declarations only and CMake based
|
||||
if (projectParts.isEmpty())
|
||||
return TestTreeItem::dependingInternalTargets(cppMM, m_filePath);
|
||||
return TestTreeItem::dependingInternalTargets(cppMM, filePath());
|
||||
QSet<QString> targets;
|
||||
for (const CppTools::ProjectPart::Ptr &part : projectParts) {
|
||||
targets.insert(part->buildSystemTarget);
|
||||
if (part->buildTargetType != ProjectExplorer::BuildTargetType::Executable)
|
||||
targets.unite(TestTreeItem::dependingInternalTargets(cppMM, m_filePath));
|
||||
targets.unite(TestTreeItem::dependingInternalTargets(cppMM, filePath()));
|
||||
}
|
||||
return targets;
|
||||
}
|
||||
|
||||
void TestTreeItem::forAllChildItems(const std::function<void(TestTreeItem *)> &pred) const
|
||||
{
|
||||
for (int row = 0, end = childCount(); row < end; ++row) {
|
||||
TestTreeItem *child = childItem(row);
|
||||
pred(child);
|
||||
child->forAllChildItems(pred);
|
||||
}
|
||||
}
|
||||
|
||||
void TestTreeItem::forFirstLevelChildItems(const std::function<void(TestTreeItem *)> &pred) const
|
||||
{
|
||||
for (int row = 0, end = childCount(); row < end; ++row)
|
||||
pred(childItem(row));
|
||||
}
|
||||
|
||||
TestTreeItem *TestTreeItem::findFirstLevelChildItem(const std::function<bool(TestTreeItem *)> &pred) const
|
||||
{
|
||||
for (int row = 0, end = childCount(); row < end; ++row) {
|
||||
TestTreeItem *child = childItem(row);
|
||||
if (pred(child))
|
||||
return child;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void TestTreeItem::copyBasicDataFrom(const TestTreeItem *other)
|
||||
{
|
||||
if (!other)
|
||||
return;
|
||||
m_name = other->m_name;
|
||||
m_filePath = other->m_filePath;
|
||||
m_type = other->m_type;
|
||||
m_checked = other->m_checked;
|
||||
m_failed = other->m_failed;
|
||||
m_line = other->m_line;
|
||||
|
||||
setName(other->name());
|
||||
setFilePath(other->filePath());
|
||||
setType(other->type());
|
||||
setLine(other->line());
|
||||
setData(0, other->checked(), Qt::CheckStateRole);
|
||||
setData(0, other->data(0, FailedRole), FailedRole);
|
||||
|
||||
m_column = other->m_column;
|
||||
m_proFile = other->m_proFile;
|
||||
m_status = other->m_status;
|
||||
}
|
||||
|
||||
inline bool TestTreeItem::modifyFilePath(const QString &filePath)
|
||||
inline bool TestTreeItem::modifyFilePath(const QString &filepath)
|
||||
{
|
||||
if (m_filePath != filePath) {
|
||||
m_filePath = filePath;
|
||||
if (filePath() != filepath) {
|
||||
setFilePath(filepath);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
inline bool TestTreeItem::modifyName(const QString &name)
|
||||
inline bool TestTreeItem::modifyName(const QString &newName)
|
||||
{
|
||||
if (m_name != name) {
|
||||
m_name = name;
|
||||
if (name() != newName) {
|
||||
setName(newName);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -371,7 +391,7 @@ inline bool TestTreeItem::modifyName(const QString &name)
|
||||
|
||||
ITestFramework *TestTreeItem::framework() const
|
||||
{
|
||||
return static_cast<ITestFramework *>(m_testBase);
|
||||
return static_cast<ITestFramework *>(testBase());
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -53,7 +53,7 @@ class TestConfiguration;
|
||||
class TestParseResult;
|
||||
enum class TestRunMode;
|
||||
|
||||
class TestTreeItem : public Utils::TypedTreeItem<TestTreeItem>
|
||||
class ITestTreeItem : public Utils::TypedTreeItem<ITestTreeItem>
|
||||
{
|
||||
public:
|
||||
|
||||
@@ -74,6 +74,51 @@ public:
|
||||
Naturally
|
||||
};
|
||||
|
||||
explicit ITestTreeItem(ITestBase *testBase,
|
||||
const QString &name = QString(),
|
||||
const QString &filePath = QString(),
|
||||
Type type = Root);
|
||||
|
||||
virtual QVariant data(int column, int role) const override;
|
||||
virtual bool setData(int column, const QVariant &data, int role) override;
|
||||
virtual Qt::ItemFlags flags(int column) const override;
|
||||
|
||||
virtual Qt::CheckState checked() const;
|
||||
virtual bool canProvideTestConfiguration() const { return false; }
|
||||
virtual TestConfiguration *testConfiguration() const { return nullptr; }
|
||||
|
||||
virtual QList<TestConfiguration *> getAllTestConfigurations() const { return {}; }
|
||||
virtual QList<TestConfiguration *> getSelectedTestConfigurations() const { return {}; }
|
||||
virtual QList<TestConfiguration *> getFailedTestConfigurations() const { return {}; }
|
||||
|
||||
const QString name() const { return m_name; }
|
||||
void setName(const QString &name) { m_name = name; }
|
||||
const QString filePath() const { return m_filePath; }
|
||||
void setFilePath(const QString &filePath) { m_filePath = filePath; }
|
||||
Type type() const { return m_type; }
|
||||
int line() const { return m_line; }
|
||||
void setLine(int line) { m_line = line;}
|
||||
ITestBase *testBase() const { return m_testBase; }
|
||||
|
||||
virtual bool lessThan(const ITestTreeItem *other, SortMode mode) const;
|
||||
QString cacheName() const { return m_filePath + ':' + m_name; }
|
||||
|
||||
protected:
|
||||
void setType(Type type) { m_type = type; }
|
||||
Qt::CheckState m_checked = Qt::Checked;
|
||||
|
||||
private:
|
||||
ITestBase *m_testBase = nullptr; // not owned
|
||||
QString m_name;
|
||||
QString m_filePath;
|
||||
Type m_type;
|
||||
int m_line = 0;
|
||||
bool m_failed = false;
|
||||
};
|
||||
|
||||
class TestTreeItem : public ITestTreeItem
|
||||
{
|
||||
public:
|
||||
explicit TestTreeItem(ITestBase *testBase,
|
||||
const QString &name = QString(),
|
||||
const QString &filePath = QString(),
|
||||
@@ -81,32 +126,23 @@ public:
|
||||
|
||||
virtual TestTreeItem *copyWithoutChildren() = 0;
|
||||
virtual QVariant data(int column, int role) const override;
|
||||
virtual bool setData(int column, const QVariant &data, int role) override;
|
||||
virtual Qt::ItemFlags flags(int column) const override;
|
||||
bool modifyTestCaseOrSuiteContent(const TestParseResult *result);
|
||||
bool modifyTestFunctionContent(const TestParseResult *result);
|
||||
bool modifyDataTagContent(const TestParseResult *result);
|
||||
bool modifyLineAndColumn(const TestParseResult *result);
|
||||
|
||||
ITestFramework *framework() const;
|
||||
const QString name() const { return m_name; }
|
||||
void setName(const QString &name) { m_name = name; }
|
||||
const QString filePath() const { return m_filePath; }
|
||||
void setFilePath(const QString &filePath) { m_filePath = filePath; }
|
||||
void setLine(int line) { m_line = line;}
|
||||
int line() const { return m_line; }
|
||||
void setColumn(int column) { m_column = column; }
|
||||
int column() const { return m_column; }
|
||||
QString proFile() const { return m_proFile; }
|
||||
void setProFile(const QString &proFile) { m_proFile = proFile; }
|
||||
virtual Qt::CheckState checked() const;
|
||||
Type type() const { return m_type; }
|
||||
void markForRemoval(bool mark);
|
||||
void markForRemovalRecursively(bool mark);
|
||||
virtual void markForRemovalRecursively(const QString &filePath);
|
||||
virtual bool removeOnSweepIfEmpty() const { return m_type == GroupNode; }
|
||||
virtual void markForRemovalRecursively(const QString &filepath);
|
||||
virtual bool removeOnSweepIfEmpty() const { return type() == GroupNode; }
|
||||
bool markedForRemoval() const { return m_status == MarkedForRemoval; }
|
||||
bool newlyAdded() const { return m_status == NewlyAdded; }
|
||||
TestTreeItem *childItem(int at) const;
|
||||
TestTreeItem *parentItem() const;
|
||||
|
||||
TestTreeItem *findChildByName(const QString &name);
|
||||
@@ -114,16 +150,10 @@ public:
|
||||
TestTreeItem *findChildByFileAndType(const QString &filePath, Type type);
|
||||
TestTreeItem *findChildByNameAndFile(const QString &name, const QString &filePath);
|
||||
|
||||
virtual bool canProvideTestConfiguration() const { return false; }
|
||||
virtual bool canProvideDebugConfiguration() const { return false; }
|
||||
virtual TestConfiguration *testConfiguration() const { return nullptr; }
|
||||
virtual TestConfiguration *debugConfiguration() const { return nullptr; }
|
||||
virtual bool canProvideDebugConfiguration() const { return false; }
|
||||
TestConfiguration *asConfiguration(TestRunMode mode) const;
|
||||
virtual QList<TestConfiguration *> getAllTestConfigurations() const;
|
||||
virtual QList<TestConfiguration *> getSelectedTestConfigurations() const;
|
||||
virtual QList<TestConfiguration *> getFailedTestConfigurations() const;
|
||||
virtual QList<TestConfiguration *> getTestConfigurationsForFile(const Utils::FilePath &fileName) const;
|
||||
virtual bool lessThan(const TestTreeItem *other, SortMode mode) const;
|
||||
virtual TestTreeItem *find(const TestParseResult *result) = 0;
|
||||
virtual TestTreeItem *findChild(const TestTreeItem *other) = 0;
|
||||
virtual bool modify(const TestParseResult *result) = 0;
|
||||
@@ -137,7 +167,9 @@ public:
|
||||
virtual bool shouldBeAddedAfterFiltering() const { return true; }
|
||||
virtual QSet<QString> internalTargets() const;
|
||||
|
||||
QString cacheName() const { return m_filePath + ':' + m_name; }
|
||||
void forAllChildItems(const std::function<void(TestTreeItem *)> &pred) const;
|
||||
void forFirstLevelChildItems(const std::function<void(TestTreeItem *)> &pred) const;
|
||||
TestTreeItem *findFirstLevelChildItem(const std::function<bool(TestTreeItem *)> &pred) const;
|
||||
protected:
|
||||
void copyBasicDataFrom(const TestTreeItem *other);
|
||||
typedef std::function<bool(const TestTreeItem *)> CompareFunction;
|
||||
@@ -145,7 +177,7 @@ protected:
|
||||
const QString &file);
|
||||
|
||||
private:
|
||||
bool modifyFilePath(const QString &filePath);
|
||||
bool modifyFilePath(const QString &filepath);
|
||||
bool modifyName(const QString &name);
|
||||
|
||||
enum Status
|
||||
@@ -155,13 +187,6 @@ private:
|
||||
Cleared
|
||||
};
|
||||
|
||||
ITestBase *m_testBase = nullptr;
|
||||
QString m_name;
|
||||
QString m_filePath;
|
||||
Qt::CheckState m_checked;
|
||||
bool m_failed = false;
|
||||
Type m_type;
|
||||
int m_line = 0;
|
||||
int m_column = 0;
|
||||
QString m_proFile;
|
||||
Status m_status = NewlyAdded;
|
||||
|
||||
@@ -119,7 +119,7 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
TestTreeItem *item = static_cast<TestTreeItem *>(index.internalPointer());
|
||||
ITestTreeItem *item = static_cast<ITestTreeItem *>(index.internalPointer());
|
||||
if (item && item->setData(index.column(), value, role)) {
|
||||
emit dataChanged(index, index, {role});
|
||||
if (role == Qt::CheckStateRole) {
|
||||
@@ -131,11 +131,14 @@ bool TestTreeModel::setData(const QModelIndex &index, const QVariant &value, int
|
||||
setData(idx, checked ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
|
||||
}
|
||||
}
|
||||
if (item->parent() != rootItem() && item->parentItem()->checked() != checked)
|
||||
revalidateCheckState(item->parentItem()); // handle parent too
|
||||
if (item->parent() != rootItem()) {
|
||||
auto parent = static_cast<ITestTreeItem *>(item->parent());
|
||||
if (parent->checked() != checked)
|
||||
revalidateCheckState(parent); // handle parent too
|
||||
}
|
||||
return true;
|
||||
} else if (role == FailedRole) {
|
||||
m_failedStateCache.insert(item, true);
|
||||
} else if (role == FailedRole) { // FIXME limit to Frameworks
|
||||
m_failedStateCache.insert(static_cast<TestTreeItem *>(item), true);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -146,7 +149,7 @@ Qt::ItemFlags TestTreeModel::flags(const QModelIndex &index) const
|
||||
if (!index.isValid())
|
||||
return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||
|
||||
TestTreeItem *item = static_cast<TestTreeItem *>(itemForIndex(index));
|
||||
ITestTreeItem *item = static_cast<ITestTreeItem *>(itemForIndex(index));
|
||||
return item->flags(index.column());
|
||||
}
|
||||
|
||||
@@ -163,7 +166,7 @@ QList<TestConfiguration *> TestTreeModel::getAllTestCases() const
|
||||
{
|
||||
QList<TestConfiguration *> result;
|
||||
for (Utils::TreeItem *frameworkRoot : *rootItem())
|
||||
result.append(static_cast<TestTreeItem *>(frameworkRoot)->getAllTestConfigurations());
|
||||
result.append(static_cast<ITestTreeItem *>(frameworkRoot)->getAllTestConfigurations());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -171,7 +174,7 @@ QList<TestConfiguration *> TestTreeModel::getSelectedTests() const
|
||||
{
|
||||
QList<TestConfiguration *> result;
|
||||
for (Utils::TreeItem *frameworkRoot : *rootItem())
|
||||
result.append(static_cast<TestTreeItem *>(frameworkRoot)->getSelectedTestConfigurations());
|
||||
result.append(static_cast<ITestTreeItem *>(frameworkRoot)->getSelectedTestConfigurations());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -179,7 +182,7 @@ QList<TestConfiguration *> TestTreeModel::getFailedTests() const
|
||||
{
|
||||
QList<TestConfiguration *> result;
|
||||
for (Utils::TreeItem *frameworkRoot : *rootItem())
|
||||
result.append(static_cast<TestTreeItem *>(frameworkRoot)->getFailedTestConfigurations());
|
||||
result.append(static_cast<ITestTreeItem *>(frameworkRoot)->getFailedTestConfigurations());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -195,13 +198,13 @@ QList<TestTreeItem *> TestTreeModel::testItemsByName(TestTreeItem *root, const Q
|
||||
{
|
||||
QList<TestTreeItem *> result;
|
||||
|
||||
root->forFirstLevelChildren([&testName, &result, this](TestTreeItem *node) {
|
||||
root->forFirstLevelChildItems([&testName, &result, this](TestTreeItem *node) {
|
||||
if (node->type() == TestTreeItem::TestSuite || node->type() == TestTreeItem::TestCase) {
|
||||
if (node->name() == testName) {
|
||||
result << node;
|
||||
return; // prioritize test suites and cases over test functions
|
||||
}
|
||||
TestTreeItem *testCase = node->findFirstLevelChild([&testName](TestTreeItem *it) {
|
||||
TestTreeItem *testCase = node->findFirstLevelChildItem([&testName](TestTreeItem *it) {
|
||||
QTC_ASSERT(it, return false);
|
||||
return (it->type() == TestTreeItem::TestCase
|
||||
|| it->type() == TestTreeItem::TestFunction) && it->name() == testName;
|
||||
@@ -218,6 +221,7 @@ QList<TestTreeItem *> TestTreeModel::testItemsByName(TestTreeItem *root, const Q
|
||||
QList<TestTreeItem *> TestTreeModel::testItemsByName(const QString &testName)
|
||||
{
|
||||
QList<TestTreeItem *> result;
|
||||
// FIXME limit to frameworks
|
||||
for (Utils::TreeItem *frameworkRoot : *rootItem())
|
||||
result << testItemsByName(static_cast<TestTreeItem *>(frameworkRoot), testName);
|
||||
|
||||
@@ -286,12 +290,12 @@ void TestTreeModel::rebuild(const QList<Utils::Id> &frameworkIds)
|
||||
TestTreeItem *frameworkRoot = framework->rootNode();
|
||||
const bool groupingEnabled = framework->grouping();
|
||||
for (int row = frameworkRoot->childCount() - 1; row >= 0; --row) {
|
||||
auto testItem = frameworkRoot->childAt(row);
|
||||
auto testItem = frameworkRoot->childItem(row);
|
||||
if (testItem->type() == TestTreeItem::GroupNode) {
|
||||
// process children of group node and delete it afterwards if necessary
|
||||
for (int childRow = testItem->childCount() - 1; childRow >= 0; --childRow) {
|
||||
// FIXME should this be done recursively until we have a non-GroupNode?
|
||||
TestTreeItem *childTestItem = testItem->childAt(childRow);
|
||||
TestTreeItem *childTestItem = testItem->childItem(childRow);
|
||||
takeItem(childTestItem);
|
||||
filterAndInsert(childTestItem, frameworkRoot, groupingEnabled);
|
||||
}
|
||||
@@ -311,8 +315,9 @@ void TestTreeModel::updateCheckStateCache()
|
||||
m_checkStateCache->evolve();
|
||||
|
||||
for (Utils::TreeItem *rootNode : *rootItem()) {
|
||||
// FIXME limit to framework items
|
||||
rootNode->forAllChildren([this](Utils::TreeItem *child) {
|
||||
auto childItem = static_cast<TestTreeItem *>(child);
|
||||
auto childItem = static_cast<ITestTreeItem *>(child);
|
||||
m_checkStateCache->insert(childItem, childItem->checked());
|
||||
});
|
||||
}
|
||||
@@ -359,7 +364,7 @@ void TestTreeModel::markForRemoval(const QString &filePath)
|
||||
for (Utils::TreeItem *frameworkRoot : *rootItem()) {
|
||||
TestTreeItem *root = static_cast<TestTreeItem *>(frameworkRoot);
|
||||
for (int childRow = root->childCount() - 1; childRow >= 0; --childRow) {
|
||||
TestTreeItem *child = root->childAt(childRow);
|
||||
TestTreeItem *child = root->childItem(childRow);
|
||||
child->markForRemovalRecursively(filePath);
|
||||
}
|
||||
}
|
||||
@@ -387,7 +392,7 @@ bool TestTreeModel::sweepChildren(TestTreeItem *item)
|
||||
{
|
||||
bool hasChanged = false;
|
||||
for (int row = item->childCount() - 1; row >= 0; --row) {
|
||||
TestTreeItem *child = item->childAt(row);
|
||||
TestTreeItem *child = item->childItem(row);
|
||||
|
||||
if (child->type() != TestTreeItem::Root && child->markedForRemoval()) {
|
||||
destroyItem(child);
|
||||
@@ -411,11 +416,11 @@ static TestTreeItem *fullCopyOf(TestTreeItem *other)
|
||||
QTC_ASSERT(other, return nullptr);
|
||||
TestTreeItem *result = other->copyWithoutChildren();
|
||||
for (int row = 0, count = other->childCount(); row < count; ++row)
|
||||
result->appendChild(fullCopyOf(other->childAt(row)));
|
||||
result->appendChild(fullCopyOf(other->childItem(row)));
|
||||
return result;
|
||||
}
|
||||
|
||||
static void applyParentCheckState(TestTreeItem *parent, TestTreeItem *newItem)
|
||||
static void applyParentCheckState(ITestTreeItem *parent, ITestTreeItem *newItem)
|
||||
{
|
||||
QTC_ASSERT(parent && newItem, return);
|
||||
|
||||
@@ -433,7 +438,7 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b
|
||||
{
|
||||
TestTreeItem *parentNode = root;
|
||||
if (groupingEnabled && item->isGroupable()) {
|
||||
parentNode = root->findFirstLevelChild([item] (const TestTreeItem *it) {
|
||||
parentNode = root->findFirstLevelChildItem([item] (const TestTreeItem *it) {
|
||||
return it->isGroupNodeFor(item);
|
||||
});
|
||||
if (!parentNode) {
|
||||
@@ -448,7 +453,7 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b
|
||||
if (auto otherItem = parentNode->findChild(item)) {
|
||||
// only handle item's children and add them to the already present one
|
||||
for (int row = 0, count = item->childCount(); row < count; ++row) {
|
||||
TestTreeItem *child = fullCopyOf(item->childAt(row));
|
||||
TestTreeItem *child = fullCopyOf(item->childItem(row));
|
||||
// use check state of the original
|
||||
child->setData(0, item->childAt(row)->checked(), Qt::CheckStateRole);
|
||||
otherItem->appendChild(child);
|
||||
@@ -471,26 +476,22 @@ void TestTreeModel::insertItemInParent(TestTreeItem *item, TestTreeItem *root, b
|
||||
}
|
||||
}
|
||||
|
||||
void TestTreeModel::revalidateCheckState(TestTreeItem *item)
|
||||
static Qt::CheckState computeCheckStateByChildren(ITestTreeItem *item)
|
||||
{
|
||||
QTC_ASSERT(item, return);
|
||||
|
||||
const TestTreeItem::Type type = item->type();
|
||||
if (type == TestTreeItem::TestSpecialFunction || type == TestTreeItem::TestDataFunction
|
||||
|| type == TestTreeItem::TestDataTag) {
|
||||
return;
|
||||
}
|
||||
const Qt::CheckState oldState = Qt::CheckState(item->data(0, Qt::CheckStateRole).toInt());
|
||||
Qt::CheckState newState = Qt::Checked;
|
||||
bool foundChecked = false;
|
||||
bool foundUnchecked = false;
|
||||
bool foundPartiallyChecked = false;
|
||||
for (int row = 0, count = item->childCount(); row < count; ++row) {
|
||||
TestTreeItem *child = item->childAt(row);
|
||||
|
||||
item->forFirstLevelChildren([&](ITestTreeItem *child) {
|
||||
if (foundPartiallyChecked || (foundChecked && foundUnchecked)) {
|
||||
newState = Qt::PartiallyChecked;
|
||||
return;
|
||||
}
|
||||
switch (child->type()) {
|
||||
case TestTreeItem::TestDataFunction:
|
||||
case TestTreeItem::TestSpecialFunction:
|
||||
continue;
|
||||
return;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@@ -498,18 +499,32 @@ void TestTreeModel::revalidateCheckState(TestTreeItem *item)
|
||||
foundChecked |= (child->checked() == Qt::Checked);
|
||||
foundUnchecked |= (child->checked() == Qt::Unchecked);
|
||||
foundPartiallyChecked |= (child->checked() == Qt::PartiallyChecked);
|
||||
if (foundPartiallyChecked || (foundChecked && foundUnchecked)) {
|
||||
newState = Qt::PartiallyChecked;
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (newState != Qt::PartiallyChecked)
|
||||
newState = foundUnchecked ? Qt::Unchecked : Qt::Checked;
|
||||
return newState;
|
||||
}
|
||||
|
||||
void TestTreeModel::revalidateCheckState(ITestTreeItem *item)
|
||||
{
|
||||
QTC_ASSERT(item, return);
|
||||
|
||||
const ITestTreeItem::Type type = item->type();
|
||||
if (type == ITestTreeItem::TestSpecialFunction || type == ITestTreeItem::TestDataFunction
|
||||
|| type == ITestTreeItem::TestDataTag) {
|
||||
return;
|
||||
}
|
||||
const Qt::CheckState oldState = Qt::CheckState(item->data(0, Qt::CheckStateRole).toInt());
|
||||
Qt::CheckState newState = computeCheckStateByChildren(item);
|
||||
if (oldState != newState) {
|
||||
item->setData(0, newState, Qt::CheckStateRole);
|
||||
emit dataChanged(item->index(), item->index(), {Qt::CheckStateRole});
|
||||
if (item->parent() != rootItem() && item->parentItem()->checked() != newState)
|
||||
revalidateCheckState(item->parentItem());
|
||||
if (item->parent() != rootItem()) {
|
||||
auto parent = static_cast<ITestTreeItem *>(item->parent());
|
||||
if (parent->checked() != newState)
|
||||
revalidateCheckState(parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -530,7 +545,7 @@ void Autotest::TestTreeModel::onDataChanged(const QModelIndex &topLeft,
|
||||
return;
|
||||
|
||||
for (int row = topLeft.row(), endRow = bottomRight.row(); row <= endRow; ++row) {
|
||||
if (auto item = static_cast<TestTreeItem *>(itemForIndex(index(row, 0, parent))))
|
||||
if (auto item = static_cast<ITestTreeItem *>(itemForIndex(index(row, 0, parent))))
|
||||
m_checkStateCache->insert(item, item->checked());
|
||||
}
|
||||
}
|
||||
@@ -564,8 +579,7 @@ void TestTreeModel::handleParseResult(const TestParseResult *result, TestTreeIte
|
||||
QTC_ASSERT(newItem, return);
|
||||
|
||||
// restore former check state and fail state if available
|
||||
newItem->forAllChildren([this](Utils::TreeItem *child) {
|
||||
auto childItem = static_cast<TestTreeItem *>(child);
|
||||
newItem->forAllChildItems([this](TestTreeItem *childItem) {
|
||||
Utils::optional<Qt::CheckState> cached = m_checkStateCache->get(childItem);
|
||||
if (cached.has_value())
|
||||
childItem->setData(0, cached.value(), Qt::CheckStateRole);
|
||||
@@ -635,7 +649,7 @@ TestTreeItem *TestTreeModel::unnamedQuickTests() const
|
||||
if (!rootNode)
|
||||
return nullptr;
|
||||
|
||||
return rootNode->findFirstLevelChild([](TestTreeItem *it) { return it->name().isEmpty(); });
|
||||
return rootNode->findFirstLevelChildItem([](TestTreeItem *it) { return it->name().isEmpty(); });
|
||||
}
|
||||
|
||||
int TestTreeModel::namedQuickTestsCount() const
|
||||
@@ -660,8 +674,8 @@ int TestTreeModel::dataTagsCount() const
|
||||
return 0;
|
||||
|
||||
int dataTagCount = 0;
|
||||
rootNode->forFirstLevelChildren([&dataTagCount](TestTreeItem *classItem) {
|
||||
classItem->forFirstLevelChildren([&dataTagCount](TestTreeItem *functionItem) {
|
||||
rootNode->forFirstLevelChildren([&dataTagCount](ITestTreeItem *classItem) {
|
||||
classItem->forFirstLevelChildren([&dataTagCount](ITestTreeItem *functionItem) {
|
||||
dataTagCount += functionItem->childCount();
|
||||
});
|
||||
});
|
||||
@@ -679,7 +693,7 @@ QMultiMap<QString, int> TestTreeModel::gtestNamesAndSets() const
|
||||
QMultiMap<QString, int> result;
|
||||
|
||||
if (TestTreeItem *rootNode = gtestRootNode()) {
|
||||
rootNode->forFirstLevelChildren([&result](TestTreeItem *child) {
|
||||
rootNode->forFirstLevelChildren([&result](ITestTreeItem *child) {
|
||||
result.insert(child->name(), child->childCount());
|
||||
});
|
||||
}
|
||||
@@ -697,7 +711,7 @@ QMap<QString, int> TestTreeModel::boostTestSuitesAndTests() const
|
||||
QMap<QString, int> result;
|
||||
|
||||
if (TestTreeItem *rootNode = boostTestRootNode()) {
|
||||
rootNode->forFirstLevelChildren([&result](TestTreeItem *child) {
|
||||
rootNode->forFirstLevelChildItems([&result](TestTreeItem *child) {
|
||||
result.insert(child->name() + '|' + child->proFile(), child->childCount());
|
||||
});
|
||||
}
|
||||
@@ -749,11 +763,11 @@ TestTreeSortFilterModel::FilterMode TestTreeSortFilterModel::toFilterMode(int f)
|
||||
bool TestTreeSortFilterModel::lessThan(const QModelIndex &left, const QModelIndex &right) const
|
||||
{
|
||||
// root items keep the intended order
|
||||
const TestTreeItem *leftItem = static_cast<TestTreeItem *>(left.internalPointer());
|
||||
if (leftItem->type() == TestTreeItem::Root)
|
||||
const ITestTreeItem *leftItem = static_cast<ITestTreeItem *>(left.internalPointer());
|
||||
if (leftItem->type() == ITestTreeItem::Root)
|
||||
return left.row() > right.row();
|
||||
|
||||
const TestTreeItem *rightItem = static_cast<TestTreeItem *>(right.internalPointer());
|
||||
const ITestTreeItem *rightItem = static_cast<ITestTreeItem *>(right.internalPointer());
|
||||
return leftItem->lessThan(rightItem, m_sortMode);
|
||||
}
|
||||
|
||||
@@ -763,12 +777,12 @@ bool TestTreeSortFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex
|
||||
if (!index.isValid())
|
||||
return false;
|
||||
|
||||
const TestTreeItem *item = static_cast<TestTreeItem *>(index.internalPointer());
|
||||
const ITestTreeItem *item = static_cast<ITestTreeItem *>(index.internalPointer());
|
||||
|
||||
switch (item->type()) {
|
||||
case TestTreeItem::TestDataFunction:
|
||||
case ITestTreeItem::TestDataFunction:
|
||||
return m_filterMode & ShowTestData;
|
||||
case TestTreeItem::TestSpecialFunction:
|
||||
case ITestTreeItem::TestSpecialFunction:
|
||||
return m_filterMode & ShowInitAndCleanup;
|
||||
default:
|
||||
return true;
|
||||
|
||||
@@ -104,7 +104,7 @@ private:
|
||||
void removeFiles(const QStringList &files);
|
||||
bool sweepChildren(TestTreeItem *item);
|
||||
void insertItemInParent(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled);
|
||||
void revalidateCheckState(TestTreeItem *item);
|
||||
void revalidateCheckState(ITestTreeItem *item);
|
||||
void setupParsingConnections();
|
||||
void filterAndInsert(TestTreeItem *item, TestTreeItem *root, bool groupingEnabled);
|
||||
QList<TestTreeItem *> testItemsByName(TestTreeItem *root, const QString &testName);
|
||||
|
||||
Reference in New Issue
Block a user