ClangcodeModel: Move test creation closer to tested code

Change-Id: Ifb6771673aa8639d2ee23d1f34b1ff821000e348
Reviewed-by: Jarek Kobus <jaroslaw.kobus@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
hjk
2024-01-19 13:32:14 +01:00
parent 4dba2a2f87
commit 8b86fe239b
7 changed files with 350 additions and 306 deletions

View File

@@ -86,16 +86,16 @@ void ClangCodeModelPlugin::initialize()
updateStaleIndexEntries.addToContainer(CppEditor::Constants::M_CONTEXT);
#ifdef WITH_TESTS
addTest<Tests::ActivationSequenceProcessorTest>();
addTest<Tests::ClangdTestCompletion>();
addTest<Tests::ClangdTestExternalChanges>();
addTest<Tests::ClangdTestFindReferences>();
addTest<Tests::ClangdTestFollowSymbol>();
addTest<Tests::ClangdTestHighlighting>();
addTest<Tests::ClangdTestIndirectChanges>();
addTest<Tests::ClangdTestLocalReferences>();
addTest<Tests::ClangdTestTooltips>();
addTest<Tests::ClangFixItTest>();
addTestCreator(createActivationSequenceProcessorTest);
addTestCreator(createClangdTestCompletion);
addTestCreator(createClangdTestExternalChanges);
addTestCreator(createClangdTestFindReferences);
addTestCreator(createClangdTestFollowSymbol);
addTestCreator(createClangdTestHighlighting);
addTestCreator(createClangdTestIndirectChanges);
addTestCreator(createClangdTestLocalReferences);
addTestCreator(createClangdTestTooltips);
addTestCreator(createClangFixItTest);
#endif
}

View File

@@ -11,7 +11,7 @@
using namespace CPlusPlus;
namespace ClangCodeModel::Internal::Tests {
namespace ClangCodeModel::Internal {
static bool resultIs(const ActivationSequenceProcessor &processor, Kind expectedKind,
int expectedOffset, int expectedNewPos)
@@ -21,6 +21,33 @@ static bool resultIs(const ActivationSequenceProcessor &processor, Kind expected
&& processor.operatorStartPosition() == expectedNewPos;
}
class ActivationSequenceProcessorTest : public QObject
{
Q_OBJECT
private slots:
void testCouldNotProcesseRandomCharacters();
void testCouldNotProcesseEmptyString();
void testDot();
void testComma();
void testLeftParenAsFunctionCall();
void testLeftParenNotAsFunctionCall();
void testColonColon();
void testArrow();
void testDotStar();
void testArrowStar();
void testDoxyGenCommentBackSlash();
void testDoxyGenCommentAt();
void testAngleStringLiteral();
void testStringLiteral();
void testSlash();
void testPound();
void testPositionIsOne();
void testPositionIsTwo();
void testPositionIsTwoWithASingleSign();
void testPositionIsThree();
};
void ActivationSequenceProcessorTest::testCouldNotProcesseRandomCharacters()
{
ActivationSequenceProcessor processor(QStringLiteral("xxx"), 3, false);
@@ -155,4 +182,11 @@ void ActivationSequenceProcessorTest::testPositionIsThree()
QVERIFY(resultIs(processor, T_ANGLE_STRING_LITERAL, 1, 2));
}
} // namespace ClangCodeModel::Internal::Tests
QObject *createActivationSequenceProcessorTest()
{
return new ActivationSequenceProcessorTest;
}
} // namespace ClangCodeModel::Internal
#include "activationsequenceprocessortest.moc"

View File

@@ -5,33 +5,8 @@
#include <QObject>
namespace ClangCodeModel::Internal::Tests {
namespace ClangCodeModel::Internal {
class ActivationSequenceProcessorTest : public QObject
{
Q_OBJECT
QObject *createActivationSequenceProcessorTest();
private slots:
void testCouldNotProcesseRandomCharacters();
void testCouldNotProcesseEmptyString();
void testDot();
void testComma();
void testLeftParenAsFunctionCall();
void testLeftParenNotAsFunctionCall();
void testColonColon();
void testArrow();
void testDotStar();
void testArrowStar();
void testDoxyGenCommentBackSlash();
void testDoxyGenCommentAt();
void testAngleStringLiteral();
void testStringLiteral();
void testSlash();
void testPound();
void testPositionIsOne();
void testPositionIsTwo();
void testPositionIsTwoWithASingleSign();
void testPositionIsThree();
};
} // namespace ClangCodeModel::Internal::Tests
} // ClangCodeModel::Internal

View File

@@ -8,25 +8,37 @@
#include "../clangmodelmanagersupport.h"
#include <coreplugin/editormanager/editormanager.h>
#include <cplusplus/FindUsages.h>
#include <cppeditor/cppcodemodelsettings.h>
#include <cppeditor/cppeditorwidget.h>
#include <cppeditor/cpptoolsreuse.h>
#include <cppeditor/cpptoolstestcase.h>
#include <cppeditor/semantichighlighter.h>
#include <languageclient/languageclientmanager.h>
#include <projectexplorer/kitmanager.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
#include <projectexplorer/target.h>
#include <qtsupport/qtkitaspect.h>
#include <texteditor/blockrange.h>
#include <texteditor/codeassist/assistproposaliteminterface.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/codeassist/textdocumentmanipulatorinterface.h>
#include <texteditor/semantichighlighter.h>
#include <texteditor/textmark.h>
#include <utils/algorithm.h>
#include <utils/environment.h>
#include <utils/filepath.h>
#include <utils/fileutils.h>
#include <utils/searchresultitem.h>
#include <utils/textutils.h>
#include <qtsupport/qtkitaspect.h>
#include <QElapsedTimer>
#include <QEventLoop>
@@ -47,22 +59,16 @@ using namespace ProjectExplorer;
using namespace TextEditor;
using namespace Utils;
namespace ClangCodeModel {
namespace Internal {
namespace Tests {
namespace ClangCodeModel::Internal {
using Range = std::tuple<int, int, int>;
} // namespace Tests
} // namespace Internal
} // namespace ClangCodeModel
} // namespace ClangCodeModel::Internal
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Tests::Range)
Q_DECLARE_METATYPE(ClangCodeModel::Internal::Range)
Q_DECLARE_METATYPE(IAssistProposal *)
namespace ClangCodeModel {
namespace Internal {
namespace Tests {
namespace ClangCodeModel::Internal {
const Usage::Tags Initialization{Usage::Tag::Declaration, Usage::Tag::Write};
@@ -92,6 +98,42 @@ int timeOutInMs()
return timeOut;
}
class ClangdTest : public QObject
{
Q_OBJECT
public:
~ClangdTest();
protected:
// Convention: base bame == name of parent dir
void setProjectFileName(const QString &fileName) { m_projectFileName = fileName; }
void setSourceFileNames(const QStringList &fileNames) { m_sourceFileNames = fileNames; }
void setMinimumVersion(int version) { m_minVersion = version; }
ClangdClient *client() const { return m_client; }
Utils::FilePath filePath(const QString &fileName) const;
TextEditor::TextDocument *document(const QString &fileName) const {
return m_sourceDocuments.value(fileName);
}
ProjectExplorer::Project *project() const { return m_project; }
void waitForNewClient(bool withIndex = true);
protected slots:
virtual void initTestCase();
private:
CppEditor::Tests::TemporaryCopiedDir *m_projectDir = nullptr;
QString m_projectFileName;
QStringList m_sourceFileNames;
QHash<QString, TextEditor::TextDocument *> m_sourceDocuments;
ProjectExplorer::Kit *m_kit = nullptr;
ProjectExplorer::Project *m_project = nullptr;
ClangdClient *m_client = nullptr;
int m_minVersion = -1;
};
ClangdTest::~ClangdTest()
{
EditorManager::closeAllEditors(false);
@@ -182,11 +224,26 @@ void ClangdTest::initTestCase()
}
}
ClangdTestFindReferences::ClangdTestFindReferences()
class ClangdTestFindReferences final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestFindReferences()
{
setProjectFileName("find-usages.pro");
setSourceFileNames({"defs.h", "main.cpp"});
}
}
private slots:
void initTestCase() override;
void init() { m_actualResults.clear(); }
void test_data();
void test();
private:
Utils::SearchResultItems m_actualResults;
};
void ClangdTestFindReferences::initTestCase()
{
@@ -333,11 +390,22 @@ void ClangdTestFindReferences::test()
}
ClangdTestFollowSymbol::ClangdTestFollowSymbol()
class ClangdTestFollowSymbol final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestFollowSymbol()
{
setProjectFileName("follow-symbol.pro");
setSourceFileNames({"main.cpp", "header.h"});
}
}
private slots:
void test_data();
void test();
void testFollowSymbolInHandler();
};
void ClangdTestFollowSymbol::test_data()
{
@@ -462,11 +530,21 @@ void ClangdTestFollowSymbol::testFollowSymbolInHandler()
timer.stop();
}
ClangdTestLocalReferences::ClangdTestLocalReferences()
class ClangdTestLocalReferences final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestLocalReferences()
{
setProjectFileName("local-references.pro");
setSourceFileNames({"references.cpp"});
}
}
private slots:
void test_data();
void test();
};
// We currently only support local variables, but if and when clangd implements
// the linkedEditingRange request, we can change the expected values for
@@ -583,11 +661,22 @@ void ClangdTestLocalReferences::test()
// This tests our help item construction, not the actual tooltip contents. Those come
// pre-formatted from clangd.
ClangdTestTooltips::ClangdTestTooltips()
class ClangdTestTooltips final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestTooltips()
{
setProjectFileName("tooltips.pro");
setSourceFileNames({"tooltips.cpp"});
}
}
private slots:
void test_data();
void test();
};
void ClangdTestTooltips::test_data()
{
@@ -718,11 +807,28 @@ void ClangdTestTooltips::test()
QCOMPARE(helpItem.docMark(), expectedMark);
}
ClangdTestHighlighting::ClangdTestHighlighting()
class ClangdTestHighlighting final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestHighlighting()
{
setProjectFileName("highlighting.pro");
setSourceFileNames({"highlighting.cpp"});
}
}
private slots:
void initTestCase() override;
void test_data();
void test();
void testIfdefedOutBlocks();
private:
TextEditor::HighlightingResults m_results;
QList<TextEditor::BlockRange> m_ifdefedOutBlocks;
};
void ClangdTestHighlighting::initTestCase()
{
@@ -1428,7 +1534,7 @@ void ClangdTestHighlighting::testIfdefedOutBlocks()
}
class Manipulator : public TextDocumentManipulatorInterface
class Manipulator final : public TextDocumentManipulatorInterface
{
public:
Manipulator()
@@ -1497,6 +1603,56 @@ private:
int m_skipPos = -1;
};
class ClangdTestCompletion final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestCompletion();
private slots:
void initTestCase() override;
void testCompletePreprocessorKeywords();
void testCompleteIncludeDirective();
void testCompleteGlobals();
void testCompleteMembers();
void testCompleteMembersFromInside();
void testCompleteMembersFromOutside();
void testCompleteMembersFromFriend();
void testFunctionAddress();
void testFunctionHints();
void testFunctionHintsFiltered();
void testFunctionHintConstructor();
void testCompleteClassAndConstructor();
void testCompletePrivateFunctionDefinition();
void testCompleteWithDotToArrowCorrection();
void testDontCompleteWithDotToArrowCorrectionForFloats();
void testCompleteCodeInGeneratedUiFile();
void testSignalCompletion_data();
void testSignalCompletion();
void testCompleteAfterProjectChange();
private:
void startCollectingHighlightingInfo();
void getProposal(const QString &fileName, TextEditor::ProposalModelPtr &proposalModel,
const QString &insertString = {}, int *cursorPos = nullptr);
static bool hasItem(TextEditor::ProposalModelPtr model, const QString &text,
const QString &detail = {});
static bool hasSnippet(TextEditor::ProposalModelPtr model, const QString &text);
static int itemsWithText(TextEditor::ProposalModelPtr model, const QString &text);
static TextEditor::AssistProposalItemInterface *getItem(
TextEditor::ProposalModelPtr model, const QString &text, const QString &detail = {});
QSet<Utils::FilePath> m_documentsWithHighlighting;
};
ClangdTestCompletion::ClangdTestCompletion()
{
setProjectFileName("completion.pro");
@@ -2006,11 +2162,20 @@ AssistProposalItemInterface *ClangdTestCompletion::getItem(
}
ClangdTestExternalChanges::ClangdTestExternalChanges()
class ClangdTestExternalChanges final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestExternalChanges()
{
setProjectFileName("completion.pro");
setSourceFileNames({"mainwindow.cpp", "main.cpp"});
}
}
private slots:
void test();
};
void ClangdTestExternalChanges::test()
{
@@ -2053,6 +2218,18 @@ void ClangdTestExternalChanges::test()
QVERIFY(waitForSignalOrTimeout(client(), &ClangdClient::textMarkCreated, timeOutInMs()));
}
class ClangdTestIndirectChanges final : public ClangdTest
{
Q_OBJECT
public:
ClangdTestIndirectChanges();
private slots:
void test();
};
ClangdTestIndirectChanges::ClangdTestIndirectChanges()
{
setProjectFileName("indirect-changes.pro");
@@ -2094,6 +2271,46 @@ void ClangdTestIndirectChanges::test()
QVERIFY(src->marks().isEmpty());
}
} // namespace Tests
} // namespace Internal
} // namespace ClangCodeModel
QObject *createClangdTestCompletion()
{
return new ClangdTestCompletion;
}
QObject *createClangdTestExternalChanges()
{
return new ClangdTestExternalChanges;
}
QObject *createClangdTestFindReferences()
{
return new ClangdTestFindReferences;
}
QObject *createClangdTestFollowSymbol()
{
return new ClangdTestFollowSymbol;
}
QObject *createClangdTestHighlighting()
{
return new ClangdTestHighlighting;
}
QObject *createClangdTestIndirectChanges()
{
return new ClangdTestIndirectChanges;
}
QObject *createClangdTestLocalReferences()
{
return new ClangdTestLocalReferences;
}
QObject *createClangdTestTooltips()
{
return new ClangdTestTooltips;
}
} // namespace ClangCodeModel::Internal
#include "clangdtests.moc"

View File

@@ -3,202 +3,18 @@
#pragma once
#include <cppeditor/cpptoolstestcase.h>
#include <texteditor/blockrange.h>
#include <texteditor/codeassist/genericproposal.h>
#include <texteditor/semantichighlighter.h>
#include <utils/fileutils.h>
#include <utils/searchresultitem.h>
#include <QHash>
#include <QObject>
#include <QSet>
#include <QStringList>
namespace ProjectExplorer {
class Kit;
class Project;
}
namespace TextEditor { class TextDocument; }
namespace ClangCodeModel::Internal {
namespace ClangCodeModel {
namespace Internal {
class ClangdClient;
namespace Tests {
QObject *createClangdTestCompletion();
QObject *createClangdTestExternalChanges();
QObject *createClangdTestFindReferences();
QObject *createClangdTestFollowSymbol();
QObject *createClangdTestHighlighting();
QObject *createClangdTestIndirectChanges();
QObject *createClangdTestLocalReferences();
QObject *createClangdTestTooltips();
class ClangdTest : public QObject
{
Q_OBJECT
public:
~ClangdTest();
protected:
// Convention: base bame == name of parent dir
void setProjectFileName(const QString &fileName) { m_projectFileName = fileName; }
void setSourceFileNames(const QStringList &fileNames) { m_sourceFileNames = fileNames; }
void setMinimumVersion(int version) { m_minVersion = version; }
ClangdClient *client() const { return m_client; }
Utils::FilePath filePath(const QString &fileName) const;
TextEditor::TextDocument *document(const QString &fileName) const {
return m_sourceDocuments.value(fileName);
}
ProjectExplorer::Project *project() const { return m_project; }
void waitForNewClient(bool withIndex = true);
protected slots:
virtual void initTestCase();
private:
CppEditor::Tests::TemporaryCopiedDir *m_projectDir = nullptr;
QString m_projectFileName;
QStringList m_sourceFileNames;
QHash<QString, TextEditor::TextDocument *> m_sourceDocuments;
ProjectExplorer::Kit *m_kit = nullptr;
ProjectExplorer::Project *m_project = nullptr;
ClangdClient *m_client = nullptr;
int m_minVersion = -1;
};
class ClangdTestFindReferences : public ClangdTest
{
Q_OBJECT
public:
ClangdTestFindReferences();
private slots:
void initTestCase() override;
void init() { m_actualResults.clear(); }
void test_data();
void test();
private:
Utils::SearchResultItems m_actualResults;
};
class ClangdTestFollowSymbol : public ClangdTest
{
Q_OBJECT
public:
ClangdTestFollowSymbol();
private slots:
void test_data();
void test();
void testFollowSymbolInHandler();
};
class ClangdTestLocalReferences : public ClangdTest
{
Q_OBJECT
public:
ClangdTestLocalReferences();
private slots:
void test_data();
void test();
};
class ClangdTestTooltips : public ClangdTest
{
Q_OBJECT
public:
ClangdTestTooltips();
private slots:
void test_data();
void test();
};
class ClangdTestHighlighting : public ClangdTest
{
Q_OBJECT
public:
ClangdTestHighlighting();
private slots:
void initTestCase() override;
void test_data();
void test();
void testIfdefedOutBlocks();
private:
TextEditor::HighlightingResults m_results;
QList<TextEditor::BlockRange> m_ifdefedOutBlocks;
};
class ClangdTestCompletion : public ClangdTest
{
Q_OBJECT
public:
ClangdTestCompletion();
private slots:
void initTestCase() override;
void testCompletePreprocessorKeywords();
void testCompleteIncludeDirective();
void testCompleteGlobals();
void testCompleteMembers();
void testCompleteMembersFromInside();
void testCompleteMembersFromOutside();
void testCompleteMembersFromFriend();
void testFunctionAddress();
void testFunctionHints();
void testFunctionHintsFiltered();
void testFunctionHintConstructor();
void testCompleteClassAndConstructor();
void testCompletePrivateFunctionDefinition();
void testCompleteWithDotToArrowCorrection();
void testDontCompleteWithDotToArrowCorrectionForFloats();
void testCompleteCodeInGeneratedUiFile();
void testSignalCompletion_data();
void testSignalCompletion();
void testCompleteAfterProjectChange();
private:
void startCollectingHighlightingInfo();
void getProposal(const QString &fileName, TextEditor::ProposalModelPtr &proposalModel,
const QString &insertString = {}, int *cursorPos = nullptr);
static bool hasItem(TextEditor::ProposalModelPtr model, const QString &text,
const QString &detail = {});
static bool hasSnippet(TextEditor::ProposalModelPtr model, const QString &text);
static int itemsWithText(TextEditor::ProposalModelPtr model, const QString &text);
static TextEditor::AssistProposalItemInterface *getItem(
TextEditor::ProposalModelPtr model, const QString &text, const QString &detail = {});
QSet<Utils::FilePath> m_documentsWithHighlighting;
};
class ClangdTestExternalChanges : public ClangdTest
{
Q_OBJECT
public:
ClangdTestExternalChanges();
private slots:
void test();
};
class ClangdTestIndirectChanges : public ClangdTest
{
Q_OBJECT
public:
ClangdTestIndirectChanges();
private slots:
void test();
};
} // namespace Tests
} // namespace Internal
} // namespace ClangCodeModel
} // ClangCodeModel::Internal

View File

@@ -5,13 +5,38 @@
#include "../clangfixitoperation.h"
#include <cppeditor/cpptoolstestcase.h>
#include <utils/changeset.h>
#include <QFile>
#include <QScopedPointer>
#include <QtTest>
#include <QVector>
namespace ClangCodeModel::Internal::Tests {
namespace ClangCodeModel::Internal {
class ClangFixItTest final : public QObject
{
Q_OBJECT
private slots:
void init();
void testAppendSemicolon();
void testComparisonVersusAssignmentChooseComparison();
void testComparisonVersusAssignmentChooseParentheses();
void testDescription();
private:
Utils::FilePath semicolonFilePath() const;
Utils::FilePath compareFilePath() const;
QString fileContent(const QString &relFilePath) const;
ClangFixIt semicolonFixIt() const;
private:
QScopedPointer<CppEditor::Tests::TemporaryCopiedDir> m_dataDir;
};
static QString qrcPath(const QString &relativeFilePath)
{
@@ -86,4 +111,11 @@ void ClangFixItTest::testComparisonVersusAssignmentChooseParentheses()
fileContent("diagnostic_comparison_fixit_expected2.cpp"));
}
} // namespace ClangCodeModel::Internal::Tests
QObject *createClangFixItTest()
{
return new ClangFixItTest;
}
} // ClangCodeModel::Internal
#include "clangfixittest.moc"

View File

@@ -3,40 +3,10 @@
#pragma once
#include <cppeditor/cpptoolstestcase.h>
#include <QObject>
#include <QScopedPointer>
#include <QString>
namespace Utils { class FilePath; }
namespace ClangCodeModel::Internal {
class ClangFixIt;
namespace Tests {
QObject *createClangFixItTest();
class ClangFixItTest : public QObject
{
Q_OBJECT
private slots:
void init();
void testAppendSemicolon();
void testComparisonVersusAssignmentChooseComparison();
void testComparisonVersusAssignmentChooseParentheses();
void testDescription();
private:
Utils::FilePath semicolonFilePath() const;
Utils::FilePath compareFilePath() const;
QString fileContent(const QString &relFilePath) const;
ClangFixIt semicolonFixIt() const;
private:
QScopedPointer<CppEditor::Tests::TemporaryCopiedDir> m_dataDir;
};
} //namespace Tests
} // namespace ClangCodeModel::Internal