summaryrefslogtreecommitdiff
path: root/src/plugins/autotest/boost/boosttestresult.cpp
blob: 80cca80cc4b37250e3e3a5c1fb9c1b97c93b0e8a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (C) 2019 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#include "boosttestresult.h"
#include "boosttestconstants.h"
#include "boosttesttreeitem.h"
#include "../testframeworkmanager.h"

#include <utils/id.h>
#include <utils/qtcassert.h>

#include <QRegularExpression>

using namespace Utils;

namespace Autotest {
namespace Internal {

static ResultHooks::OutputStringHook outputStringHook(const QString &testCaseName)
{
    return [testCaseName](const TestResult &result, bool selected) {
        const QString &desc = result.description();
        QString output;
        switch (result.result()) {
        case ResultType::Pass:
        case ResultType::Fail:
            output = testCaseName;
            if (selected && !desc.isEmpty())
                output.append('\n').append(desc);
            break;
        default:
            output = desc;
            if (!selected)
                output = output.split('\n').first();
        }
        return output;
    };
}

static bool matches(const FilePath &fileName, const FilePath &projectFile, const QString &testCaseName,
             const QString &testSuiteName, const BoostTestTreeItem *item)
{
    // due to lacking information on the result side and a not fully appropriate tree we
    // might end up here with a differing set of tests, but it's the best we can do
    if (!item)
        return false;
    if (testCaseName.isEmpty()) // a top level module node
        return item->proFile() == projectFile;
    if (item->proFile() != projectFile)
        return false;
    if (!fileName.isEmpty() && fileName != item->filePath())
        return false;

    QString fullName = "::" + testCaseName;
    fullName.prepend(testSuiteName.isEmpty() ? QString(BoostTest::Constants::BOOST_MASTER_SUITE)
                                              : testSuiteName);

    BoostTestTreeItem::TestStates states = item->state();
    if (states & BoostTestTreeItem::Templated) {
        const QRegularExpression regex(
            QRegularExpression::wildcardToRegularExpression(item->fullName() + "<*>"));
        return regex.match(fullName).hasMatch();
    } else if (states & BoostTestTreeItem::Parameterized) {
        const QRegularExpression regex(
            QRegularExpression::anchoredPattern(item->fullName() + "_\\d+"));
        return regex.isValid() && regex.match(fullName).hasMatch();
    }
    return item->fullName() == fullName;
}

static ResultHooks::FindTestItemHook findTestItemHook(const FilePath &projectFile,
                                                      const QString &testCaseName,
                                                      const QString &testSuiteName)
{
    return [=](const TestResult &result) -> ITestTreeItem * {
        const Id id = Id(Constants::FRAMEWORK_PREFIX).withSuffix(BoostTest::Constants::FRAMEWORK_NAME);
        ITestFramework *framework = TestFrameworkManager::frameworkForId(id);
        QTC_ASSERT(framework, return nullptr);
        const TestTreeItem *rootNode = framework->rootNode();
        if (!rootNode)
            return nullptr;

        return rootNode->findAnyChild([&](const TreeItem *item) {
            const auto testTreeItem = static_cast<const BoostTestTreeItem *>(item);
            return testTreeItem && matches(result.fileName(), projectFile, testCaseName,
                                           testSuiteName, testTreeItem);
        });
    };
}

struct BoostTestData
{
    QString m_testCaseName;
    QString m_testSuiteName;
};

static ResultHooks::DirectParentHook directParentHook(const QString &testCaseName,
                                                      const QString &testSuiteName)
{
    return [=](const TestResult &result, const TestResult &other, bool *) -> bool {
        if (!other.extraData().canConvert<BoostTestData>())
            return false;
        const BoostTestData otherData = other.extraData().value<BoostTestData>();

        if (result.result() != ResultType::TestStart)
            return false;

        bool thisModule = (testCaseName.isEmpty() && testSuiteName.isEmpty());
        bool thisSuite = (testCaseName.isEmpty() && !testSuiteName.isEmpty());
        bool thisCase = (!testCaseName.isEmpty());

        bool otherSuite = otherData.m_testCaseName.isEmpty() && !otherData.m_testSuiteName.isEmpty();
        bool otherCase = !otherData.m_testCaseName.isEmpty();

        if (otherSuite)
            return thisSuite ? otherData.m_testSuiteName.startsWith(testSuiteName + '/') : thisModule;

        if (otherCase) {
            if (thisCase)
                return otherData.m_testCaseName == testCaseName && otherData.m_testSuiteName == testSuiteName;
            if (thisSuite)
                return otherData.m_testSuiteName == testSuiteName;
            if (thisModule)
                return otherData.m_testSuiteName.isEmpty();
        }
        return false;
    };
}

BoostTestResult::BoostTestResult(const QString &id, const QString &name,
                                 const FilePath &projectFile, const QString &testCaseName,
                                 const QString &testSuiteName)
    : TestResult(id, name, {QVariant::fromValue(BoostTestData{testCaseName, testSuiteName}),
                            outputStringHook(testCaseName),
                            findTestItemHook(projectFile, testCaseName, testSuiteName),
                            directParentHook(testCaseName, testSuiteName)})
{}

} // namespace Internal
} // namespace Autotest

Q_DECLARE_METATYPE(Autotest::Internal::BoostTestData);