Commit 88d667ab authored by Igor Kushnir's avatar Igor Kushnir
Browse files

Fix test_files-clang failure with Clang 13

The test fails on my system and on KDevelop CI like this:
QDEBUG : TestFiles::testFiles(basicdeclsandcontexts.cpp) "identifier" FAILED: Declaration's identifier ("(unnamed struct at /home/jenkins/workspace/KDevelop/kdevelop/kf5-qt5 SUSEQt5.15/plugins/clang/tests/files/basicdeclsandcontexts.cpp:97:1)") doesn't match test data (""). (Declaration on line 97 in /home/jenkins/workspace/KDevelop/kdevelop/kf5-qt5 SUSEQt5.15/plugins/clang/tests/files/basicdeclsandcontexts.cpp)
QDEBUG : TestFiles::testFiles(basicdeclsandcontexts.cpp) "identifier" FAILED: Declaration's identifier ("(unnamed union at /home/jenkins/workspace/KDevelop/kdevelop/kf5-qt5 SUSEQt5.15/plugins/clang/tests/files/basicdeclsandcontexts.cpp:100:1)") doesn't match test data (""). (Declaration on line 100 in /home/jenkins/workspace/KDevelop/kdevelop/kf5-qt5 SUSEQt5.15/plugins/clang/tests/files/basicdeclsandcontexts.cpp)
FAIL!  : TestFiles::testFiles(basicdeclsandcontexts.cpp) 'validator.testsPassed()' returned FALSE. ()
   Loc: [/home/jenkins/workspace/KDevelop/kdevelop/kf5-qt5 SUSEQt5.15/plugins/clang/tests/test_files.cpp(116)]

The test fix is based on adding testDataAdjuster callback to
DeclarationValidator. It should be possible to reuse this new interface
to solve future test_files* failures.

I haven't verified that the test passes with older Clang versions. But
made sure that the test data is adjusted to the values from the parent
commit when Clang version is older than 13. So it should pass.
parent ee69d8b3
......@@ -12,12 +12,14 @@
#include <QJsonDocument>
#include <utility>
namespace KDevelop {
class DeclarationValidatorPrivate
{
public:
DeclarationValidatorPrivate() : testsPassed(true) {}
bool testsPassed;
DeclarationValidator::TestDataEditor testDataAdjuster{};
bool testsPassed = true;
};
QByteArray preprocess(QByteArray json)
......@@ -36,8 +38,8 @@ QByteArray preprocess(QByteArray json)
return '{' + json + '}';
}
DeclarationValidator::DeclarationValidator()
: d_ptr(new DeclarationValidatorPrivate)
DeclarationValidator::DeclarationValidator(TestDataEditor testDataAdjuster)
: d_ptr(new DeclarationValidatorPrivate{std::move(testDataAdjuster)})
{
}
DeclarationValidator::~DeclarationValidator()
......@@ -62,7 +64,9 @@ void DeclarationValidator::visit(Declaration* declaration)
if (error.error == 0) {
QVariantMap testData = doc.toVariant().toMap();
if (d->testDataAdjuster) {
d->testDataAdjuster(testData);
}
if (!KDevelop::runTests(testData, declaration))
d->testsPassed = false;
} else
......
......@@ -11,6 +11,11 @@
#include "language/duchain/ducontext.h"
#include <QMap>
#include <QVariant>
#include <functional>
namespace KDevelop {
class DeclarationValidatorPrivate;
......@@ -18,7 +23,8 @@ class KDEVPLATFORMTESTS_EXPORT DeclarationValidator
: public DUChainVisitor
{
public:
DeclarationValidator();
using TestDataEditor = std::function<void(QVariantMap& testData)>;
explicit DeclarationValidator(TestDataEditor testDataAdjuster = nullptr);
~DeclarationValidator() override;
virtual bool testsPassed() const;
......
......@@ -93,8 +93,14 @@ namespace bar
};
}
/// "identifier" : "", "range" : "[(96, 0), (96, 0)]"
/**
* "identifier" : "(unnamed struct at ${TEST_FILES_DIR}/basicdeclsandcontexts.cpp:100:1)",
* "range" : "[(99, 0), (99, 6)]"
*/
struct {} unnamedStructObject;
/// "identifier" : "", "range" : "[(99, 0), (99, 0)]"
/**
* "identifier" : "(unnamed union at ${TEST_FILES_DIR}/basicdeclsandcontexts.cpp:106:1)",
* "range" : "[(105, 0), (105, 5)]"
*/
union {} unnamedUnionObject;
......@@ -29,6 +29,7 @@
#include <QTest>
#include <QLoggingCategory>
#include <QProcess>
#include <QRegularExpression>
#include <QVersionNumber>
using namespace KDevelop;
......@@ -40,7 +41,52 @@ bool isCudaAvailable()
{
return QProcess::execute(QStringLiteral("clang"), {QStringLiteral("-xcuda"), QStringLiteral("-fsyntax-only"), QProcess::nullDevice()}) == 0;
}
QRegularExpression rangeRegularExpression()
{
const auto capturedCursorRegexp = QStringLiteral("(\\(\\d+, \\d+\\))");
const auto rangeRegexp = QStringLiteral("\\[%1, %2\\]").arg(capturedCursorRegexp, capturedCursorRegexp);
return QRegularExpression{QRegularExpression::anchoredPattern(rangeRegexp)};
}
void adjustTestData(QVariantMap& testData)
{
const auto idIt = testData.find("identifier");
if (idIt == testData.end()) {
return; // nothing to adjust
}
static const QLatin1String testFilesDirVariableName("${TEST_FILES_DIR}");
QCOMPARE(idIt->userType(), QMetaType::QString);
auto identifier = idIt->toString();
if (!identifier.contains(testFilesDirVariableName)) {
return; // nothing to adjust
}
if (QVersionNumber::fromString(ClangHelpers::clangVersion()) >= QVersionNumber(13, 0, 0)) {
*idIt = identifier.replace(testFilesDirVariableName, TEST_FILES_DIR);
return; // done
}
// Older Clang versions return an empty identifier for unnamed struct and anonymous union.
*idIt = QString();
// KDevelop's Visitor::createDeclarationCommon() assigns the range's end to its start when
// the identifier is empty, so the same is done below.
const auto rangeIt = testData.find("range");
if (rangeIt == testData.end()) {
return; // no range => nothing left to adjust
}
QCOMPARE(rangeIt->userType(), QMetaType::QString);
auto range = rangeIt->toString();
static const auto regexp = rangeRegularExpression();
QVERIFY(range.contains(regexp));
*rangeIt = range.replace(regexp, "[\\1, \\1]");
}
} // unnamed namespace
void TestFiles::initTestCase()
{
......@@ -103,7 +149,7 @@ void TestFiles::testFiles()
QVERIFY(top);
DUChainReadLocker lock;
DeclarationValidator validator;
DeclarationValidator validator(adjustTestData);
top->visit(validator);
const auto problems = top->problems();
......
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