2017-01-30 11:24:46 +01:00
|
|
|
/****************************************************************************
|
|
|
|
|
**
|
|
|
|
|
** Copyright (C) 2016 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"
|
|
|
|
|
|
2017-01-31 14:21:05 +01:00
|
|
|
#include "fakeprocess.h"
|
2019-01-31 10:30:58 +01:00
|
|
|
#include "filesystem-utilities.h"
|
2018-01-22 14:21:01 +01:00
|
|
|
|
2019-02-25 19:07:19 +01:00
|
|
|
#include "mockbuilddependenciesstorage.h"
|
2018-09-11 17:02:45 +02:00
|
|
|
#include "mockclangpathwatcher.h"
|
|
|
|
|
#include "mockpchmanagerclient.h"
|
2017-01-30 11:24:46 +01:00
|
|
|
#include "testenvironment.h"
|
|
|
|
|
|
2018-01-22 14:21:01 +01:00
|
|
|
#include <refactoringdatabaseinitializer.h>
|
|
|
|
|
#include <filepathcaching.h>
|
2018-09-11 14:02:59 +02:00
|
|
|
#include <generatedfiles.h>
|
2017-01-30 11:24:46 +01:00
|
|
|
#include <pchcreator.h>
|
2018-09-11 17:02:45 +02:00
|
|
|
#include <precompiledheadersupdatedmessage.h>
|
2018-09-27 17:52:44 +02:00
|
|
|
#include <progressmessage.h>
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2018-01-22 14:21:01 +01:00
|
|
|
#include <sqlitedatabase.h>
|
|
|
|
|
|
2017-01-30 11:24:46 +01:00
|
|
|
#include <QFileInfo>
|
|
|
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
2018-11-12 19:27:51 +01:00
|
|
|
using ClangBackEnd::FilePath;
|
2017-09-21 11:43:59 +02:00
|
|
|
using ClangBackEnd::FilePathId;
|
2018-11-12 19:27:51 +01:00
|
|
|
using ClangBackEnd::FilePathIds;
|
|
|
|
|
using ClangBackEnd::FilePathView;
|
2018-09-11 14:02:59 +02:00
|
|
|
using ClangBackEnd::GeneratedFiles;
|
2017-01-30 11:24:46 +01:00
|
|
|
using ClangBackEnd::IdPaths;
|
2018-12-17 12:06:57 +01:00
|
|
|
using ClangBackEnd::IncludeSearchPathType;
|
|
|
|
|
using ClangBackEnd::PchTask;
|
2017-01-30 11:24:46 +01:00
|
|
|
using ClangBackEnd::ProjectPartPch;
|
2018-11-12 19:27:51 +01:00
|
|
|
using ClangBackEnd::SourceEntries;
|
|
|
|
|
using ClangBackEnd::SourceEntry;
|
|
|
|
|
using ClangBackEnd::SourceType;
|
2017-02-01 13:43:28 +01:00
|
|
|
using ClangBackEnd::V2::FileContainer;
|
2018-12-17 12:06:57 +01:00
|
|
|
using ClangBackEnd::ProjectPartContainer;
|
2017-11-16 17:48:53 +01:00
|
|
|
|
2017-02-01 13:43:28 +01:00
|
|
|
using Utils::PathString;
|
2017-01-30 11:24:46 +01:00
|
|
|
using Utils::SmallString;
|
|
|
|
|
|
2017-08-29 12:54:10 +02:00
|
|
|
using UnitTests::EndsWith;
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2018-12-17 12:06:57 +01:00
|
|
|
MATCHER_P2(HasIdAndType,
|
|
|
|
|
sourceId,
|
|
|
|
|
sourceType,
|
|
|
|
|
std::string(negation ? "hasn't" : "has")
|
|
|
|
|
+ PrintToString(ClangBackEnd::SourceEntry(sourceId, sourceType, -1)))
|
2018-11-12 19:27:51 +01:00
|
|
|
{
|
|
|
|
|
const ClangBackEnd::SourceEntry &entry = arg;
|
|
|
|
|
return entry.sourceId == sourceId && entry.sourceType == sourceType;
|
|
|
|
|
}
|
|
|
|
|
|
2017-01-30 11:24:46 +01:00
|
|
|
class PchCreator: public ::testing::Test
|
|
|
|
|
{
|
|
|
|
|
protected:
|
2019-02-14 13:29:21 +01:00
|
|
|
PchCreator() { creator.setUnsavedFiles({generatedFile}); }
|
2018-09-11 14:02:59 +02:00
|
|
|
|
2018-01-22 14:21:01 +01:00
|
|
|
ClangBackEnd::FilePathId id(ClangBackEnd::FilePathView path)
|
|
|
|
|
{
|
2018-09-11 17:02:45 +02:00
|
|
|
return creator.filePathCache().filePathId(path);
|
2018-01-22 14:21:01 +01:00
|
|
|
}
|
2017-01-30 11:24:46 +01:00
|
|
|
|
|
|
|
|
protected:
|
2018-01-22 14:21:01 +01:00
|
|
|
Sqlite::Database database{":memory:", Sqlite::JournalMode::Memory};
|
|
|
|
|
ClangBackEnd::RefactoringDatabaseInitializer<Sqlite::Database> databaseInitializer{database};
|
2018-11-12 19:27:51 +01:00
|
|
|
FilePath main1Path = TESTDATA_DIR "/builddependencycollector/project/main3.cpp";
|
|
|
|
|
FilePath main2Path = TESTDATA_DIR "/builddependencycollector/project/main2.cpp";
|
|
|
|
|
FilePath header1Path = TESTDATA_DIR "/builddependencycollector/project/header1.h";
|
|
|
|
|
FilePath header2Path = TESTDATA_DIR "/builddependencycollector/project/header2.h";
|
|
|
|
|
FilePath generatedFilePath = TESTDATA_DIR "/builddependencycollector/project/generated_file.h";
|
2018-09-11 17:02:45 +02:00
|
|
|
TestEnvironment environment;
|
2019-02-14 13:29:21 +01:00
|
|
|
FileContainer generatedFile{generatedFilePath.clone(), "#pragma once", {}};
|
2018-09-11 17:02:45 +02:00
|
|
|
NiceMock<MockPchManagerClient> mockPchManagerClient;
|
2019-01-24 13:19:03 +01:00
|
|
|
NiceMock<MockClangPathWatcher> mockClangPathWatcher;
|
2019-02-25 19:07:19 +01:00
|
|
|
NiceMock<MockBuildDependenciesStorage> mockBuildDependenciesStorage;
|
|
|
|
|
ClangBackEnd::PchCreator creator{environment,
|
|
|
|
|
database,
|
|
|
|
|
mockPchManagerClient,
|
|
|
|
|
mockClangPathWatcher,
|
|
|
|
|
mockBuildDependenciesStorage};
|
2018-12-17 12:06:57 +01:00
|
|
|
PchTask pchTask1{
|
2019-03-13 15:09:30 +01:00
|
|
|
1,
|
2019-01-24 13:19:03 +01:00
|
|
|
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
|
|
|
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
|
|
|
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h")},
|
2019-02-25 19:07:19 +01:00
|
|
|
{id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
2018-12-17 12:06:57 +01:00
|
|
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
2019-02-25 19:07:19 +01:00
|
|
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
|
|
|
|
id(generatedFilePath),
|
|
|
|
|
id(main2Path)},
|
2018-12-17 12:06:57 +01:00
|
|
|
{},
|
|
|
|
|
{},
|
|
|
|
|
{},
|
|
|
|
|
{{TESTDATA_DIR "/builddependencycollector/system", 2, IncludeSearchPathType::BuiltIn},
|
|
|
|
|
{TESTDATA_DIR "/builddependencycollector/external", 1, IncludeSearchPathType::System}},
|
|
|
|
|
{{TESTDATA_DIR "/builddependencycollector/project", 1, IncludeSearchPathType::User}},
|
|
|
|
|
};
|
2017-01-30 11:24:46 +01:00
|
|
|
};
|
|
|
|
|
using PchCreatorSlowTest = PchCreator;
|
|
|
|
|
using PchCreatorVerySlowTest = PchCreator;
|
|
|
|
|
|
2018-12-17 12:06:57 +01:00
|
|
|
TEST_F(PchCreator, CreateProjectPartPchFileContent)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2018-12-17 12:06:57 +01:00
|
|
|
auto content = creator.generatePchIncludeFileContent(pchTask1.includes);
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2017-08-29 12:54:10 +02:00
|
|
|
ASSERT_THAT(std::string(content),
|
2018-11-12 19:27:51 +01:00
|
|
|
AllOf(HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/project/header2.h\"\n"),
|
|
|
|
|
HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external1.h\"\n"),
|
|
|
|
|
HasSubstr("#include \"" TESTDATA_DIR "/builddependencycollector/external/external2.h\"\n")));
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(PchCreator, CreateProjectPartClangCompilerArguments)
|
|
|
|
|
{
|
2019-01-30 13:59:30 +01:00
|
|
|
auto arguments = creator.generateClangCompilerArguments(std::move(pchTask1), "project.pch");
|
2018-12-17 12:06:57 +01:00
|
|
|
|
|
|
|
|
ASSERT_THAT(arguments,
|
|
|
|
|
ElementsAre("clang++",
|
2019-02-28 19:22:22 +01:00
|
|
|
"-w",
|
2019-02-13 13:37:24 +01:00
|
|
|
"-DNOMINMAX",
|
2018-12-17 12:06:57 +01:00
|
|
|
"-x",
|
|
|
|
|
"c++-header",
|
|
|
|
|
"-std=c++98",
|
|
|
|
|
"-nostdinc",
|
2019-01-30 09:07:45 +01:00
|
|
|
"-nostdinc++",
|
2018-12-17 12:06:57 +01:00
|
|
|
"-I",
|
2019-04-07 15:57:42 +02:00
|
|
|
toNativePath(resourcePath()),
|
|
|
|
|
"-I",
|
2019-03-13 15:09:30 +01:00
|
|
|
toNativePath(TESTDATA_DIR "/builddependencycollector/project"),
|
2018-12-17 12:06:57 +01:00
|
|
|
"-isystem",
|
2019-03-13 15:09:30 +01:00
|
|
|
toNativePath(TESTDATA_DIR "/builddependencycollector/external"),
|
2018-12-17 12:06:57 +01:00
|
|
|
"-isystem",
|
2019-03-13 15:09:30 +01:00
|
|
|
toNativePath(TESTDATA_DIR "/builddependencycollector/system"),
|
2018-12-17 12:06:57 +01:00
|
|
|
"-o",
|
2019-01-30 13:59:30 +01:00
|
|
|
"project.pch"));
|
2018-12-17 12:06:57 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(PchCreator, CreateProjectPartClangCompilerArgumentsWithSystemPch)
|
|
|
|
|
{
|
|
|
|
|
pchTask1.systemPchPath = "system.pch";
|
|
|
|
|
|
2019-01-30 13:59:30 +01:00
|
|
|
auto arguments = creator.generateClangCompilerArguments(std::move(pchTask1), "project.pch");
|
2018-12-17 12:06:57 +01:00
|
|
|
|
|
|
|
|
ASSERT_THAT(arguments,
|
|
|
|
|
ElementsAre("clang++",
|
2019-02-28 19:22:22 +01:00
|
|
|
"-w",
|
2019-02-13 13:37:24 +01:00
|
|
|
"-DNOMINMAX",
|
2018-12-17 12:06:57 +01:00
|
|
|
"-x",
|
|
|
|
|
"c++-header",
|
|
|
|
|
"-std=c++98",
|
|
|
|
|
"-nostdinc",
|
2019-01-30 09:07:45 +01:00
|
|
|
"-nostdinc++",
|
2018-12-17 12:06:57 +01:00
|
|
|
"-I",
|
2019-04-07 15:57:42 +02:00
|
|
|
toNativePath(resourcePath()),
|
|
|
|
|
"-I",
|
2019-03-13 15:09:30 +01:00
|
|
|
toNativePath(TESTDATA_DIR "/builddependencycollector/project"),
|
2018-12-17 12:06:57 +01:00
|
|
|
"-isystem",
|
2019-03-13 15:09:30 +01:00
|
|
|
toNativePath(TESTDATA_DIR "/builddependencycollector/external"),
|
2018-12-17 12:06:57 +01:00
|
|
|
"-isystem",
|
2019-03-13 15:09:30 +01:00
|
|
|
toNativePath(TESTDATA_DIR "/builddependencycollector/system"),
|
2018-12-17 12:06:57 +01:00
|
|
|
"-Xclang",
|
|
|
|
|
"-include-pch",
|
|
|
|
|
"-Xclang",
|
|
|
|
|
"system.pch",
|
|
|
|
|
"-o",
|
2019-01-30 13:59:30 +01:00
|
|
|
"project.pch"));
|
2018-09-11 17:02:45 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TEST_F(PchCreatorVerySlowTest, ProjectPartPchsSendToPchManagerClient)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2018-12-17 12:06:57 +01:00
|
|
|
creator.generatePch(std::move(pchTask1));
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2018-09-11 17:02:45 +02:00
|
|
|
EXPECT_CALL(mockPchManagerClient,
|
|
|
|
|
precompiledHeadersUpdated(
|
|
|
|
|
Field(&ClangBackEnd::PrecompiledHeadersUpdatedMessage::projectPartPchs,
|
|
|
|
|
ElementsAre(Eq(creator.projectPartPch())))));
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2018-09-11 17:02:45 +02:00
|
|
|
creator.doInMainThreadAfterFinished();
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
2019-02-25 19:07:19 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, SourcesAreWatchedAfterSucess)
|
2019-01-24 13:19:03 +01:00
|
|
|
{
|
|
|
|
|
creator.generatePch(std::move(pchTask1));
|
|
|
|
|
|
2019-02-25 19:07:19 +01:00
|
|
|
EXPECT_CALL(mockClangPathWatcher,
|
|
|
|
|
updateIdPaths(ElementsAre(AllOf(
|
2019-03-13 15:09:30 +01:00
|
|
|
Field(&ClangBackEnd::IdPaths::id, 1),
|
2019-02-25 19:07:19 +01:00
|
|
|
Field(&ClangBackEnd::IdPaths::filePathIds,
|
|
|
|
|
UnorderedElementsAre(
|
|
|
|
|
id(TESTDATA_DIR "/builddependencycollector/project/header2.h"),
|
|
|
|
|
id(TESTDATA_DIR "/builddependencycollector/external/external1.h"),
|
|
|
|
|
id(TESTDATA_DIR "/builddependencycollector/external/external2.h"),
|
|
|
|
|
id(TESTDATA_DIR "/builddependencycollector/project/main2.cpp")))))));
|
2019-01-24 13:19:03 +01:00
|
|
|
|
|
|
|
|
creator.doInMainThreadAfterFinished();
|
|
|
|
|
}
|
|
|
|
|
|
2019-02-25 19:07:19 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, SourcesAreNotWatchedAfterFail)
|
2019-01-24 13:19:03 +01:00
|
|
|
{
|
|
|
|
|
pchTask1.systemIncludeSearchPaths = {};
|
|
|
|
|
pchTask1.projectIncludeSearchPaths = {};
|
|
|
|
|
creator.generatePch(std::move(pchTask1));
|
|
|
|
|
|
|
|
|
|
EXPECT_CALL(mockClangPathWatcher,
|
|
|
|
|
updateIdPaths(
|
2019-03-13 15:09:30 +01:00
|
|
|
ElementsAre(AllOf(Field(&ClangBackEnd::IdPaths::id, 1),
|
2019-01-24 13:19:03 +01:00
|
|
|
Field(&ClangBackEnd::IdPaths::filePathIds, IsEmpty())))));
|
|
|
|
|
|
|
|
|
|
creator.doInMainThreadAfterFinished();
|
|
|
|
|
}
|
2017-01-30 11:24:46 +01:00
|
|
|
|
2019-02-25 19:07:19 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, PchCreationTimeStampsAreUpdated)
|
|
|
|
|
{
|
|
|
|
|
creator.generatePch(std::move(pchTask1));
|
|
|
|
|
|
2019-03-13 15:09:30 +01:00
|
|
|
EXPECT_CALL(mockBuildDependenciesStorage, updatePchCreationTimeStamp(_, Eq(1)));
|
2019-02-25 19:07:19 +01:00
|
|
|
|
|
|
|
|
creator.doInMainThreadAfterFinished();
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-17 12:06:57 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, ProjectPartPchForCreatesPchForPchTask)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2018-12-17 12:06:57 +01:00
|
|
|
creator.generatePch(std::move(pchTask1));
|
2018-09-11 17:02:45 +02:00
|
|
|
|
|
|
|
|
ASSERT_THAT(creator.projectPartPch(),
|
2019-03-13 15:09:30 +01:00
|
|
|
AllOf(Field(&ProjectPartPch::projectPartId, Eq(1)),
|
2018-09-11 17:02:45 +02:00
|
|
|
Field(&ProjectPartPch::pchPath, Not(IsEmpty())),
|
|
|
|
|
Field(&ProjectPartPch::lastModified, Not(Eq(-1)))));
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|
|
|
|
|
|
2018-09-11 17:02:45 +02:00
|
|
|
TEST_F(PchCreatorVerySlowTest, ProjectPartPchCleared)
|
|
|
|
|
{
|
2018-12-17 12:06:57 +01:00
|
|
|
creator.generatePch(std::move(pchTask1));
|
2018-09-11 17:02:45 +02:00
|
|
|
|
|
|
|
|
creator.clear();
|
|
|
|
|
|
2019-03-13 15:09:30 +01:00
|
|
|
ASSERT_FALSE(creator.projectPartPch().isValid());
|
2018-09-11 17:02:45 +02:00
|
|
|
}
|
|
|
|
|
|
2019-02-25 19:07:19 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, SourcesCleared)
|
|
|
|
|
{
|
|
|
|
|
creator.generatePch(std::move(pchTask1));
|
|
|
|
|
|
|
|
|
|
creator.clear();
|
|
|
|
|
|
|
|
|
|
ASSERT_THAT(creator.sources(), IsEmpty());
|
|
|
|
|
}
|
|
|
|
|
|
2019-01-22 14:38:39 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, ClangToolCleared)
|
|
|
|
|
{
|
|
|
|
|
creator.generatePch(std::move(pchTask1));
|
|
|
|
|
|
|
|
|
|
creator.clear();
|
|
|
|
|
|
|
|
|
|
ASSERT_TRUE(creator.clangTool().isClean());
|
|
|
|
|
}
|
|
|
|
|
|
2018-12-17 12:06:57 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, FaultyProjectPartPchForCreatesFaultyPchForPchTask)
|
2017-01-30 11:24:46 +01:00
|
|
|
{
|
2019-03-13 15:09:30 +01:00
|
|
|
PchTask faultyPchTask{
|
|
|
|
|
0,
|
|
|
|
|
{id(TESTDATA_DIR "/builddependencycollector/project/faulty.cpp")},
|
|
|
|
|
{},
|
|
|
|
|
{{"DEFINE", "1", 1}},
|
|
|
|
|
{},
|
|
|
|
|
{},
|
|
|
|
|
{{TESTDATA_DIR "/builddependencycollector/external", 1, IncludeSearchPathType::System}},
|
|
|
|
|
{{TESTDATA_DIR "/builddependencycollector/project", 1, IncludeSearchPathType::User}}};
|
2018-09-11 17:02:45 +02:00
|
|
|
|
2018-12-17 12:06:57 +01:00
|
|
|
creator.generatePch(std::move(faultyPchTask));
|
2018-09-11 17:02:45 +02:00
|
|
|
|
|
|
|
|
ASSERT_THAT(creator.projectPartPch(),
|
2019-03-13 15:09:30 +01:00
|
|
|
AllOf(Field(&ProjectPartPch::projectPartId, Eq(0)),
|
2018-09-11 17:02:45 +02:00
|
|
|
Field(&ProjectPartPch::pchPath, IsEmpty()),
|
2019-02-25 19:07:19 +01:00
|
|
|
Field(&ProjectPartPch::lastModified, Gt(0))));
|
2017-02-16 18:25:19 +01:00
|
|
|
}
|
|
|
|
|
|
2019-01-22 14:38:39 +01:00
|
|
|
TEST_F(PchCreatorVerySlowTest, GeneratedFile)
|
|
|
|
|
{
|
|
|
|
|
creator.clear();
|
|
|
|
|
|
|
|
|
|
creator.setUnsavedFiles({generatedFile});
|
|
|
|
|
|
|
|
|
|
ASSERT_FALSE(creator.clangTool().isClean());
|
|
|
|
|
}
|
2017-01-30 11:24:46 +01:00
|
|
|
}
|