diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2022-06-22 14:31:33 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2022-06-24 10:05:54 +0000 |
commit | 224be9add898d60ec979efe4c0fd14312aeba858 (patch) | |
tree | b5770770c4a2fdb418dd3c9635a130f8b6c20864 | |
parent | e4d692a689a682a2b7476a9d5d4f115b81377b2b (diff) |
ClangTools: Move over a test from unittest
Change-Id: Id61a0bdb8e46ead4de8ad0298e62afb7b9fbcfb4
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
21 files changed, 407 insertions, 408 deletions
diff --git a/src/plugins/clangtools/CMakeLists.txt b/src/plugins/clangtools/CMakeLists.txt index 51bccb10233..cdb6f279214 100644 --- a/src/plugins/clangtools/CMakeLists.txt +++ b/src/plugins/clangtools/CMakeLists.txt @@ -51,4 +51,5 @@ extend_qtc_plugin(ClangTools clangtoolspreconfiguredsessiontests.cpp clangtoolspreconfiguredsessiontests.h clangtoolsunittests.cpp clangtoolsunittests.h clangtoolsunittests.qrc + readexporteddiagnosticstest.cpp readexporteddiagnosticstest.h ) diff --git a/src/plugins/clangtools/clangtools.qbs b/src/plugins/clangtools/clangtools.qbs index c3683ee17f7..01d680e537c 100644 --- a/src/plugins/clangtools/clangtools.qbs +++ b/src/plugins/clangtools/clangtools.qbs @@ -91,6 +91,8 @@ QtcPlugin { "clangtoolsunittests.cpp", "clangtoolsunittests.h", "clangtoolsunittests.qrc", + "readexporteddiagnosticstest.cpp", + "readexporteddiagnosticstest.h", ] } diff --git a/src/plugins/clangtools/clangtoolsplugin.cpp b/src/plugins/clangtools/clangtoolsplugin.cpp index bcd759a23ba..615e7e59d3e 100644 --- a/src/plugins/clangtools/clangtoolsplugin.cpp +++ b/src/plugins/clangtools/clangtoolsplugin.cpp @@ -34,6 +34,7 @@ #include "settingswidget.h" #ifdef WITH_TESTS +#include "readexporteddiagnosticstest.h" #include "clangtoolspreconfiguredsessiontests.h" #include "clangtoolsunittests.h" #endif @@ -193,6 +194,7 @@ QVector<QObject *> ClangToolsPlugin::createTestObjects() const #ifdef WITH_TESTS tests << new PreconfiguredSessionTests; tests << new ClangToolsUnitTests; + tests << new ReadExportedDiagnosticsTest; #endif return tests; } diff --git a/src/plugins/clangtools/clangtoolsunittests.qrc b/src/plugins/clangtools/clangtoolsunittests.qrc index 598de3e3671..54bb416eab5 100644 --- a/src/plugins/clangtools/clangtoolsunittests.qrc +++ b/src/plugins/clangtools/clangtoolsunittests.qrc @@ -22,5 +22,17 @@ <file>unit-tests/clangtidy_clazy/clangtidy_clazy.pro</file> <file>unit-tests/clangtidy_clazy/clazy_example.cpp</file> <file>unit-tests/clangtidy_clazy/tidy_example.cpp</file> + <file>unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp</file> + <file>unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml</file> + <file>unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml</file> + <file>unit-tests/exported-diagnostics/clazy.qgetenv.cpp</file> + <file>unit-tests/exported-diagnostics/clazy.qgetenv.yaml</file> + <file>unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml</file> + <file>unit-tests/exported-diagnostics/CMakeLists.txt</file> + <file>unit-tests/exported-diagnostics/empty.yaml</file> + <file>unit-tests/exported-diagnostics/main.cpp</file> + <file>unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp</file> + <file>unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml</file> + <file>unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml</file> </qresource> </RCC> diff --git a/src/plugins/clangtools/readexporteddiagnosticstest.cpp b/src/plugins/clangtools/readexporteddiagnosticstest.cpp new file mode 100644 index 00000000000..6bd9eb5a116 --- /dev/null +++ b/src/plugins/clangtools/readexporteddiagnosticstest.cpp @@ -0,0 +1,314 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#include "readexporteddiagnosticstest.h" + +#include "clangtoolslogfilereader.h" + +#include <cppeditor/cpptoolstestcase.h> +#include <utils/fileutils.h> +#include <utils/hostosinfo.h> +#include <utils/qtcassert.h> + +#include <QtTest> + +using namespace CppEditor::Tests; +using namespace Debugger; +using namespace Utils; + +namespace ClangTools::Internal { + +const char asciiWord[] = "FOO"; +const char asciiMultiLine[] = "FOO\nBAR"; +const char asciiMultiLine_dos[] = "FOO\r\nBAR"; +const char nonAsciiMultiLine[] = "\xc3\xbc" "\n" + "\xe4\xba\x8c" "\n" + "\xf0\x90\x8c\x82" "X"; + +ReadExportedDiagnosticsTest::ReadExportedDiagnosticsTest() + : m_baseDir(new TemporaryCopiedDir(":/clangtools/unit-tests/exported-diagnostics")) {} + +ReadExportedDiagnosticsTest::~ReadExportedDiagnosticsTest() { delete m_baseDir; } + +void ReadExportedDiagnosticsTest::initTestCase() { QVERIFY(m_baseDir->isValid()); } +void ReadExportedDiagnosticsTest::init() { m_message.clear(); } + +void ReadExportedDiagnosticsTest::testNonExistingFile() +{ + const Diagnostics diags = readExportedDiagnostics("nonExistingFile.yaml", {}, &m_message); + QVERIFY(diags.isEmpty()); + QVERIFY(!m_message.isEmpty()); +} + +void ReadExportedDiagnosticsTest::testEmptyFile() +{ + const Diagnostics diags = readExportedDiagnostics(filePath("empty.yaml"), {}, &m_message); + QVERIFY(diags.isEmpty()); + QVERIFY2(m_message.isEmpty(), qPrintable(m_message)); +} + +void ReadExportedDiagnosticsTest::testUnexpectedFileContents() +{ + const Diagnostics diags = readExportedDiagnostics(filePath("tidy.modernize-use-nullptr.cpp"), + {}, &m_message); + QVERIFY(!m_message.isEmpty()); + QVERIFY(diags.isEmpty()); +} + +static QString appendYamlSuffix(const char *filePathFragment) +{ + const QString yamlSuffix = QLatin1String(Utils::HostOsInfo::isWindowsHost() + ? "_win.yaml" : ".yaml"); + return filePathFragment + yamlSuffix; +} + +void ReadExportedDiagnosticsTest::testTidy() +{ + const FilePath sourceFile = filePath("tidy.modernize-use-nullptr.cpp"); + const QString exportedFile = createFile( + filePath(appendYamlSuffix("tidy.modernize-use-nullptr")).toString(), + sourceFile.toString()); + Diagnostic expectedDiag; + expectedDiag.name = "modernize-use-nullptr"; + expectedDiag.location = {sourceFile, 2, 25}; + expectedDiag.description = "use nullptr [modernize-use-nullptr]"; + expectedDiag.type = "warning"; + expectedDiag.hasFixits = true; + expectedDiag.explainingSteps = { + ExplainingStep{"nullptr", + expectedDiag.location, + {expectedDiag.location, {sourceFile, 2, 26}}, + true}}; + const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), + {}, &m_message); + + QVERIFY2(m_message.isEmpty(), qPrintable(m_message)); + QCOMPARE(diags, {expectedDiag}); +} + +void ReadExportedDiagnosticsTest::testAcceptDiagsFromFilePaths_None() +{ + const QString sourceFile = filePath("tidy.modernize-use-nullptr.cpp").toString(); + const QString exportedFile = createFile(filePath("tidy.modernize-use-nullptr.yaml").toString(), + sourceFile); + const auto acceptNone = [](const Utils::FilePath &) { return false; }; + const Diagnostics diags = readExportedDiagnostics(FilePath::fromString(exportedFile), + acceptNone, &m_message); + QVERIFY2(m_message.isEmpty(), qPrintable(m_message)); + QVERIFY(diags.isEmpty()); +} + +// Diagnostics from clang (static) analyzer passed through via clang-tidy +void ReadExportedDiagnosticsTest::testTidy_ClangAnalyzer() +{ + const FilePath sourceFile = filePath("clang-analyzer.dividezero.cpp"); + const QString exportedFile = createFile( + filePath(appendYamlSuffix("clang-analyzer.dividezero")).toString(), + sourceFile.toString()); + Diagnostic expectedDiag; + expectedDiag.name = "clang-analyzer-core.DivideZero"; + expectedDiag.location = {sourceFile, 4, 15}; + expectedDiag.description = "Division by zero [clang-analyzer-core.DivideZero]"; + expectedDiag.type = "warning"; + expectedDiag.hasFixits = false; + expectedDiag.explainingSteps = { + ExplainingStep{"Assuming 'z' is equal to 0", + {sourceFile, 3, 7}, + {}, + false, + }, + ExplainingStep{"Taking true branch", + {sourceFile, 3, 3}, + {}, + false, + }, + ExplainingStep{"Division by zero", + {sourceFile, 4, 15}, + {}, + false, + }, + }; + const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), + {}, &m_message); + QVERIFY2(m_message.isEmpty(), qPrintable(m_message)); + QCOMPARE(diags, {expectedDiag}); +} + +void ReadExportedDiagnosticsTest::testClazy() +{ + const FilePath sourceFile = filePath("clazy.qgetenv.cpp"); + const QString exportedFile = createFile(filePath(appendYamlSuffix("clazy.qgetenv")).toString(), + sourceFile.toString()); + Diagnostic expectedDiag; + expectedDiag.name = "clazy-qgetenv"; + expectedDiag.location = {sourceFile, 7, 5}; + expectedDiag.description = "qgetenv().isEmpty() allocates. Use qEnvironmentVariableIsEmpty() instead [clazy-qgetenv]"; + expectedDiag.type = "warning"; + expectedDiag.hasFixits = true; + expectedDiag.explainingSteps = { + ExplainingStep{"qEnvironmentVariableIsEmpty", + expectedDiag.location, + {expectedDiag.location, {sourceFile, 7, 12}}, + true + }, + ExplainingStep{")", + {sourceFile, 7, 18}, + {{sourceFile, 7, 18}, {sourceFile, 7, 29}}, + true}, + }; + const Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), + {}, &m_message); + QVERIFY2(m_message.isEmpty(), qPrintable(m_message)); + QCOMPARE(diags, {expectedDiag}); +} + +void ReadExportedDiagnosticsTest::testOffsetInvalidText() +{ + QVERIFY(!byteOffsetInUtf8TextToLineColumn(nullptr, 0)); +} + +void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_EmptyInput() +{ + QVERIFY(!byteOffsetInUtf8TextToLineColumn("", 0)); +} + +void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_Before() +{ + QVERIFY(!byteOffsetInUtf8TextToLineColumn(asciiWord, -1)); +} + +void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_After() +{ + QVERIFY(!byteOffsetInUtf8TextToLineColumn(asciiWord, 3)); +} + +void ReadExportedDiagnosticsTest::testOffsetInvalidOffset_NotFirstByteOfMultiByte() +{ + QVERIFY(!byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 1)); +} + +void ReadExportedDiagnosticsTest::testOffsetStartOfFirstLine() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 0); + QVERIFY(info); + QCOMPARE(info->line, 1); + QCOMPARE(info->column, 1); +} + +void ReadExportedDiagnosticsTest::testOffsetEndOfFirstLine() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 2); + QVERIFY(info); + QCOMPARE(info->line, 1); + QCOMPARE(info->column, 3); +} + +// The invocation +// +// clang-tidy "-checks=-*,readability-braces-around-statements" /path/to/file +// +// for the code +// +// void f(bool b) +// { +// if (b) +// f(b); +// } +// +// emits +// +// 3:11: warning: statement should be inside braces [readability-braces-around-statements] +// +// The newline in the if-line is considered as column 11, which is normally not visible in the +// editor. +void ReadExportedDiagnosticsTest::testOffsetOffsetPointingToLineSeparator_unix() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 3); + QVERIFY(info); + QCOMPARE(info->line, 1); + QCOMPARE(info->column, 4); +} + +// For a file with dos style line endings ("\r\n"), clang-tidy points to '\r'. +void ReadExportedDiagnosticsTest::testOffsetOffsetPointingToLineSeparator_dos() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine_dos, 3); + QVERIFY(info); + QCOMPARE(info->line, 1); + QCOMPARE(info->column, 4); +} + +void ReadExportedDiagnosticsTest::testOffsetStartOfSecondLine() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 4); + QVERIFY(info); + QCOMPARE(info->line, 2); + QCOMPARE(info->column, 1); +} + +void ReadExportedDiagnosticsTest::testOffsetMultiByteCodePoint1() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 3); + QVERIFY(info); + QCOMPARE(info->line, 2); + QCOMPARE(info->column, 1); +} + +void ReadExportedDiagnosticsTest::testOffsetMultiByteCodePoint2() +{ + const auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 11); + QVERIFY(info); + QCOMPARE(info->line, 3); + QCOMPARE(info->column, 2); +} + +// Replace FILE_PATH with a real absolute file path in the *.yaml files. +QString ReadExportedDiagnosticsTest::createFile(const QString &yamlFilePath, + const QString &filePathToInject) const +{ + QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return QString()); + const Utils::FilePath newFileName = FilePath::fromString(m_baseDir->absolutePath( + QFileInfo(yamlFilePath).fileName().toLocal8Bit())); + + Utils::FileReader reader; + if (QTC_GUARD(reader.fetch(Utils::FilePath::fromString(yamlFilePath), + QIODevice::ReadOnly | QIODevice::Text))) { + QByteArray contents = reader.data(); + contents.replace("FILE_PATH", filePathToInject.toLocal8Bit()); + + Utils::FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text); + QTC_CHECK(fileSaver.write(contents)); + QTC_CHECK(fileSaver.finalize()); + } + + return newFileName.toString(); +} + +FilePath ReadExportedDiagnosticsTest::filePath(const QString &fileName) const +{ + return FilePath::fromString(m_baseDir->absolutePath(fileName.toUtf8())); +} + +} // namespace ClangTools::Internal diff --git a/src/plugins/clangtools/readexporteddiagnosticstest.h b/src/plugins/clangtools/readexporteddiagnosticstest.h new file mode 100644 index 00000000000..007ae7802e8 --- /dev/null +++ b/src/plugins/clangtools/readexporteddiagnosticstest.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2022 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QObject> +#include <QString> + +namespace CppEditor::Tests { class TemporaryCopiedDir; } +namespace Utils { class FilePath; } + +namespace ClangTools::Internal { + +class ReadExportedDiagnosticsTest : public QObject +{ + Q_OBJECT +public: + ReadExportedDiagnosticsTest(); + ~ReadExportedDiagnosticsTest(); + +private slots: + void initTestCase(); + void init(); + + void testNonExistingFile(); + void testEmptyFile(); + void testUnexpectedFileContents(); + void testTidy(); + void testAcceptDiagsFromFilePaths_None(); + void testTidy_ClangAnalyzer(); + void testClazy(); + + void testOffsetInvalidText(); + void testOffsetInvalidOffset_EmptyInput(); + void testOffsetInvalidOffset_Before(); + void testOffsetInvalidOffset_After(); + void testOffsetInvalidOffset_NotFirstByteOfMultiByte(); + void testOffsetStartOfFirstLine(); + void testOffsetEndOfFirstLine(); + void testOffsetOffsetPointingToLineSeparator_unix(); + void testOffsetOffsetPointingToLineSeparator_dos(); + void testOffsetStartOfSecondLine(); + void testOffsetMultiByteCodePoint1(); + void testOffsetMultiByteCodePoint2(); + +private: + QString createFile(const QString &yamlFilePath, const QString &filePathToInject) const; + Utils::FilePath filePath(const QString &fileName) const; + + CppEditor::Tests::TemporaryCopiedDir * const m_baseDir; + QString m_message; +}; + +} // namespace ClangTools::Internal diff --git a/tests/unit/unittest/data/clangtools/CMakeLists.txt b/src/plugins/clangtools/unit-tests/exported-diagnostics/CMakeLists.txt index b445f81b7dd..b445f81b7dd 100644 --- a/tests/unit/unittest/data/clangtools/CMakeLists.txt +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/CMakeLists.txt diff --git a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp index 5f623dc114b..5f623dc114b 100644 --- a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.cpp +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.cpp diff --git a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml index d19c5887a98..d19c5887a98 100644 --- a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero.yaml diff --git a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero_win.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml index d54844d25cf..d54844d25cf 100644 --- a/tests/unit/unittest/data/clangtools/clang-analyzer.dividezero_win.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clang-analyzer.dividezero_win.yaml diff --git a/tests/unit/unittest/data/clangtools/clazy.qgetenv.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.cpp index e04518821cb..e04518821cb 100644 --- a/tests/unit/unittest/data/clangtools/clazy.qgetenv.cpp +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.cpp diff --git a/tests/unit/unittest/data/clangtools/clazy.qgetenv.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.yaml index a465a1ca638..a465a1ca638 100644 --- a/tests/unit/unittest/data/clangtools/clazy.qgetenv.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv.yaml diff --git a/tests/unit/unittest/data/clangtools/clazy.qgetenv_win.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml index c80a701373b..c80a701373b 100644 --- a/tests/unit/unittest/data/clangtools/clazy.qgetenv_win.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/clazy.qgetenv_win.yaml diff --git a/tests/unit/unittest/data/clangtools/empty.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/empty.yaml index e69de29bb2d..e69de29bb2d 100644 --- a/tests/unit/unittest/data/clangtools/empty.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/empty.yaml diff --git a/tests/unit/unittest/data/clangtools/main.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/main.cpp index df38a776481..df38a776481 100644 --- a/tests/unit/unittest/data/clangtools/main.cpp +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/main.cpp diff --git a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.cpp b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp index fedae863306..fedae863306 100644 --- a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.cpp +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.cpp diff --git a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml index 7724d3bdfcb..7724d3bdfcb 100644 --- a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr.yaml diff --git a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr_win.yaml b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml index c6bb6766adb..c6bb6766adb 100644 --- a/tests/unit/unittest/data/clangtools/tidy.modernize-use-nullptr_win.yaml +++ b/src/plugins/clangtools/unit-tests/exported-diagnostics/tidy.modernize-use-nullptr_win.yaml diff --git a/tests/unit/unittest/CMakeLists.txt b/tests/unit/unittest/CMakeLists.txt index d51a8a56adc..e661df8237b 100644 --- a/tests/unit/unittest/CMakeLists.txt +++ b/tests/unit/unittest/CMakeLists.txt @@ -142,11 +142,6 @@ add_custom_command(TARGET unittest POST_BUILD ) extend_qtc_test(unittest - SOURCES - readexporteddiagnostics-test.cpp -) - -extend_qtc_test(unittest CONDITION TARGET GoogleBenchmark DEPENDS GoogleBenchmark SOURCES @@ -327,27 +322,6 @@ endif() extend_qtc_test(unittest DEPENDS Utils CPlusPlus) -find_package(yaml-cpp QUIET MODULE) - -extend_qtc_test(unittest - DEPENDS yaml-cpp - DEFINES CLANGTOOLS_STATIC_LIBRARY - SOURCES_PREFIX ../../../src/plugins/clangtools - SOURCES - clangtoolsdiagnostic.cpp - clangtoolsdiagnostic.h - clangtoolslogfilereader.cpp - clangtoolslogfilereader.h -) - -extend_qtc_test(unittest - DEFINES DEBUGGER_STATIC_LIBRARY - SOURCES_PREFIX ../../../src/plugins/debugger - SOURCES - analyzer/diagnosticlocation.cpp - analyzer/diagnosticlocation.h -) - extend_qtc_test(unittest SOURCES_PREFIX ../../../src/plugins/coreplugin DEFINES CORE_STATIC_LIBRARY diff --git a/tests/unit/unittest/readexporteddiagnostics-test.cpp b/tests/unit/unittest/readexporteddiagnostics-test.cpp deleted file mode 100644 index dcd0a00ee79..00000000000 --- a/tests/unit/unittest/readexporteddiagnostics-test.cpp +++ /dev/null @@ -1,350 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2019 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of Qt Creator. -** -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 3 as published by the Free Software -** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-3.0.html. -** -****************************************************************************/ - -#include "googletest.h" - -#include <clangtools/clangtoolslogfilereader.h> - -#include <utils/fileutils.h> -#include <utils/qtcassert.h> - -#define TESTDATA TESTDATA_DIR "/clangtools/" - -using namespace ClangTools::Internal; -using Debugger::DiagnosticLocation; - -namespace { - -class ReadExportedDiagnostics : public ::testing::Test -{ -protected: - void SetUp() override - { - ASSERT_TRUE(temporaryDir.isValid()); - } - - // Replace FILE_PATH with a real absolute file path in the *.yaml files. - QString createFile(const QString &yamlFilePath, const QString &filePathToInject) - { - QTC_ASSERT(QDir::isAbsolutePath(filePathToInject), return QString()); - const Utils::FilePath newFileName = temporaryDir.filePath(QFileInfo(yamlFilePath).fileName()); - - Utils::FileReader reader; - if (QTC_GUARD(reader.fetch(Utils::FilePath::fromString(yamlFilePath), - QIODevice::ReadOnly | QIODevice::Text))) { - QByteArray contents = reader.data(); - contents.replace("FILE_PATH", filePathToInject.toLocal8Bit()); - - Utils::FileSaver fileSaver(newFileName, QIODevice::WriteOnly | QIODevice::Text); - QTC_CHECK(fileSaver.write(contents)); - QTC_CHECK(fileSaver.finalize()); - } - - return newFileName.toString(); - } - -protected: - QString errorMessage; - Utils::TemporaryDirectory temporaryDir{"clangtools-tests-XXXXXX"}; -}; - -TEST_F(ReadExportedDiagnostics, NotExistingFile) -{ - Diagnostics diags = readExportedDiagnostics("notExistingFile.yaml", - {}, - &errorMessage); - - ASSERT_THAT(diags, IsEmpty()); - ASSERT_FALSE(errorMessage.isEmpty()); -} - -TEST_F(ReadExportedDiagnostics, EmptyFile) -{ - Diagnostics diags = readExportedDiagnostics(TESTDATA "empty.yaml", - {}, - &errorMessage); - - ASSERT_THAT(diags, IsEmpty()); - ASSERT_TRUE(errorMessage.isEmpty()); -} - -TEST_F(ReadExportedDiagnostics, UnexpectedFileContents) -{ - const QString sourceFile = TESTDATA "tidy.modernize-use-nullptr.cpp"; - - Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(sourceFile), - {}, - &errorMessage); - - ASSERT_FALSE(errorMessage.isEmpty()); - ASSERT_THAT(diags, IsEmpty()); -} - -static QString appendYamlSuffix(const char *filePathFragment) -{ - const QString yamlSuffix = QLatin1String(Utils::HostOsInfo::isWindowsHost() - ? "_win.yaml" : ".yaml"); - return filePathFragment + yamlSuffix; -} - -TEST_F(ReadExportedDiagnostics, Tidy) -{ - const Utils::FilePath sourceFile = Utils::FilePath::fromString( - TESTDATA "tidy.modernize-use-nullptr.cpp"); - const QString exportedFile = createFile(appendYamlSuffix(TESTDATA "tidy.modernize-use-nullptr"), - sourceFile.toString()); - Diagnostic expectedDiag; - expectedDiag.name = "modernize-use-nullptr"; - expectedDiag.location = {sourceFile, 2, 25}; - expectedDiag.description = "use nullptr [modernize-use-nullptr]"; - expectedDiag.type = "warning"; - expectedDiag.hasFixits = true; - expectedDiag.explainingSteps = { - ExplainingStep{"nullptr", - expectedDiag.location, - {expectedDiag.location, {sourceFile, 2, 26}}, - true}}; - - Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), - {}, - &errorMessage); - - ASSERT_TRUE(errorMessage.isEmpty()); - ASSERT_THAT(diags, ElementsAre(expectedDiag)); -} - -TEST_F(ReadExportedDiagnostics, AcceptDiagsFromFilePaths_None) -{ - const QString sourceFile = TESTDATA "tidy.modernize-use-nullptr.cpp"; - const QString exportedFile = createFile(TESTDATA "tidy.modernize-use-nullptr.yaml", sourceFile); - const auto acceptNone = [](const Utils::FilePath &) { return false; }; - - Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), - acceptNone, - &errorMessage); - - ASSERT_TRUE(errorMessage.isEmpty()); - ASSERT_THAT(diags, IsEmpty()); -} - -// Diagnostics from clang (static) analyzer passed through via clang-tidy -TEST_F(ReadExportedDiagnostics, Tidy_ClangAnalyzer) -{ - const Utils::FilePath sourceFile = Utils::FilePath::fromString(TESTDATA - "clang-analyzer.dividezero.cpp"); - const QString exportedFile = createFile(appendYamlSuffix(TESTDATA "clang-analyzer.dividezero"), - sourceFile.toString()); - Diagnostic expectedDiag; - expectedDiag.name = "clang-analyzer-core.DivideZero"; - expectedDiag.location = {sourceFile, 4, 15}; - expectedDiag.description = "Division by zero [clang-analyzer-core.DivideZero]"; - expectedDiag.type = "warning"; - expectedDiag.hasFixits = false; - expectedDiag.explainingSteps = { - ExplainingStep{"Assuming 'z' is equal to 0", - {sourceFile, 3, 7}, - {}, - false, - }, - ExplainingStep{"Taking true branch", - {sourceFile, 3, 3}, - {}, - false, - }, - ExplainingStep{"Division by zero", - {sourceFile, 4, 15}, - {}, - false, - }, - }; - - Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), - {}, - &errorMessage); - - ASSERT_TRUE(errorMessage.isEmpty()); - ASSERT_THAT(diags, ElementsAre(expectedDiag)); -} - -TEST_F(ReadExportedDiagnostics, Clazy) -{ - const Utils::FilePath sourceFile = Utils::FilePath::fromString(TESTDATA "clazy.qgetenv.cpp"); - const QString exportedFile = createFile(appendYamlSuffix(TESTDATA "clazy.qgetenv"), - sourceFile.toString()); - Diagnostic expectedDiag; - expectedDiag.name = "clazy-qgetenv"; - expectedDiag.location = {sourceFile, 7, 5}; - expectedDiag.description = "qgetenv().isEmpty() allocates. Use qEnvironmentVariableIsEmpty() instead [clazy-qgetenv]"; - expectedDiag.type = "warning"; - expectedDiag.hasFixits = true; - expectedDiag.explainingSteps = { - ExplainingStep{"qEnvironmentVariableIsEmpty", - expectedDiag.location, - {expectedDiag.location, {sourceFile, 7, 12}}, - true - }, - ExplainingStep{")", - {sourceFile, 7, 18}, - {{sourceFile, 7, 18}, {sourceFile, 7, 29}}, - true}, - }; - - Diagnostics diags = readExportedDiagnostics(Utils::FilePath::fromString(exportedFile), - {}, - &errorMessage); - - ASSERT_TRUE(errorMessage.isEmpty()); - ASSERT_THAT(diags, ElementsAre(expectedDiag)); -} - -class ByteOffsetInUtf8TextToLineColumn : public ::testing::Test -{ -protected: - const char *empty = ""; - const char *asciiWord = "FOO"; - const char *asciiMultiLine = "FOO\nBAR"; - const char *asciiMultiLine_dos = "FOO\r\nBAR"; - const char *asciiEmptyMultiLine = "\n\n"; - // U+00FC - 2 code units in UTF8, 1 in UTF16 - LATIN SMALL LETTER U WITH DIAERESIS - // U+4E8C - 3 code units in UTF8, 1 in UTF16 - CJK UNIFIED IDEOGRAPH-4E8C - // U+10302 - 4 code units in UTF8, 2 in UTF16 - OLD ITALIC LETTER KE - const char *nonAsciiMultiLine = "\xc3\xbc" "\n" - "\xe4\xba\x8c" "\n" - "\xf0\x90\x8c\x82" "X"; - - // Convenience - const char *text = nullptr; -}; - -TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidText) -{ - ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(nullptr, 0)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_EmptyInput) -{ - ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(empty, 0)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_Before) -{ - ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(asciiWord, -1)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_After) -{ - ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(asciiWord, 3)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, InvalidOffset_NotFirstByteOfMultiByte) -{ - ASSERT_FALSE(byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 1)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, StartOfFirstLine) -{ - auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 0); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(1)); - ASSERT_THAT(info->column, Eq(1)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, EndOfFirstLine) -{ - auto info = byteOffsetInUtf8TextToLineColumn(asciiWord, 2); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(1)); - ASSERT_THAT(info->column, Eq(3)); -} - -// The invocation -// -// clang-tidy "-checks=-*,readability-braces-around-statements" /path/to/file -// -// for the code -// -// void f(bool b) -// { -// if (b) -// f(b); -// } -// -// emits -// -// 3:11: warning: statement should be inside braces [readability-braces-around-statements] -// -// The new line in the if-line is considered as column 11, which is normally not visible in the -// editor. -TEST_F(ByteOffsetInUtf8TextToLineColumn, OffsetPointingToLineSeparator_unix) -{ - auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 3); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(1)); - ASSERT_THAT(info->column, Eq(4)); -} - -// For a file with dos style line endings ("\r\n"), clang-tidy points to '\r'. -TEST_F(ByteOffsetInUtf8TextToLineColumn, OffsetPointingToLineSeparator_dos) -{ - auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine_dos, 3); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(1)); - ASSERT_THAT(info->column, Eq(4)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, StartOfSecondLine) -{ - auto info = byteOffsetInUtf8TextToLineColumn(asciiMultiLine, 4); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(2)); - ASSERT_THAT(info->column, Eq(1)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, MultiByteCodePoint1) -{ - auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 3); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(2)); - ASSERT_THAT(info->column, Eq(1)); -} - -TEST_F(ByteOffsetInUtf8TextToLineColumn, MultiByteCodePoint2) -{ - auto info = byteOffsetInUtf8TextToLineColumn(nonAsciiMultiLine, 11); - - ASSERT_TRUE(info); - ASSERT_THAT(info->line, Eq(3)); - ASSERT_THAT(info->column, Eq(2)); -} - -} // namespace - -#undef TESTDATA diff --git a/tests/unit/unittest/unittest.qbs b/tests/unit/unittest/unittest.qbs index d53e858b5da..21fa47cb433 100644 --- a/tests/unit/unittest/unittest.qbs +++ b/tests/unit/unittest/unittest.qbs @@ -23,7 +23,6 @@ Project { Depends { name: "sqlite_sources" } Depends { name: "Core" } Depends { name: "CPlusPlus" } - Depends { name: "yaml-cpp" } Depends { name: "Qt"; submodules: ["network", "widgets", "testlib"] } @@ -40,9 +39,7 @@ Project { "QT_RESTRICTED_CAST_FROM_ASCII", "QT_USE_FAST_OPERATOR_PLUS", "QT_USE_FAST_CONCATENATION", - "CLANGTOOLS_STATIC_LIBRARY", "CPPEDITOR_STATIC_LIBRARY", - "DEBUGGER_STATIC_LIBRARY", "UNIT_TESTS", "DONT_CHECK_MESSAGE_COUNTER", 'QTC_RESOURCE_DIR="' + path + "/../../../share/qtcreator" + '"', @@ -173,14 +170,6 @@ Project { ] Group { - name: "libclang tests" - condition: libclang.present && (!qbs.targetOS.contains("windows") || libclang.llvmBuildModeMatches) - files: [ - "readexporteddiagnostics-test.cpp", - ] - } - - Group { name: "benchmark test" condition: benchmark.present files: "smallstring-benchmark.cpp" @@ -203,26 +192,5 @@ Project { "cppprojectfile.h", ] } - - Group { - name: "sources from clangtools" - condition: libclang.present - prefix: "../../../src/plugins/clangtools/" - files: [ - "clangtoolsdiagnostic.cpp", - "clangtoolsdiagnostic.h", - "clangtoolslogfilereader.cpp", - "clangtoolslogfilereader.h", - ] - } - - Group { - name: "sources from Debugger" - prefix: "../../../src/plugins/debugger/analyzer/" - files: [ - "diagnosticlocation.cpp", - "diagnosticlocation.h", - ] - } } } |