blob: 52ac97294e0f66d490cbd8c9ca1d6ec98d32d223 [file] [log] [blame]
// Copyright 2018 The Goma Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "compiler_info_builder.h"
#include "compiler_flags_parser.h"
#include "compiler_info.h"
#include "compiler_type_specific_collection.h"
#include "cxx/cxx_compiler_info.h"
#include "gtest/gtest.h"
#include "mypath.h"
#include "path.h"
#include "subprocess.h"
#include "unittest_util.h"
#include "util.h"
namespace devtools_goma {
class CompilerInfoBuilderTest : public testing::Test {
protected:
void SetUp() override { CheckTempDirectory(GetGomaTmpDir()); }
void AppendPredefinedMacros(const string& macro, CompilerInfoData* cid) {
cid->mutable_cxx()->set_predefined_macros(cid->cxx().predefined_macros() +
macro);
}
int FindValue(const std::unordered_map<string, int>& map, const string& key) {
const auto& it = map.find(key);
if (it == map.end())
return 0;
return it->second;
}
string TestDir() {
// This module is in out\Release.
const std::string parent_dir = file::JoinPath(GetMyDirectory(), "..");
const std::string top_dir = file::JoinPath(parent_dir, "..");
return file::JoinPath(top_dir, "test");
}
CompilerTypeSpecificCollection cts_collection_;
};
TEST_F(CompilerInfoBuilderTest, DependsOnCwd) {
{
std::unique_ptr<CompilerInfoData> cid(new CompilerInfoData);
cid->mutable_cxx()->add_cxx_system_include_paths("/usr/local/include");
cid->mutable_cxx()->add_cxx_system_include_paths(
"/usr/lib/gcc/x86_64-linux-gnu/4.4.3/include");
cid->mutable_cxx()->add_cxx_system_include_paths(
"/usr/lib/gcc/x86_64-linux-gnu/4.4.3/include-fixed");
cid->mutable_cxx()->add_cxx_system_include_paths("/usr/include");
cid->set_found(true);
CxxCompilerInfo info(std::move(cid));
EXPECT_FALSE(info.DependsOnCwd("/tmp"));
EXPECT_TRUE(info.DependsOnCwd("/usr"));
}
{
std::unique_ptr<CompilerInfoData> cid(new CompilerInfoData);
cid->mutable_cxx()->add_cxx_system_include_paths("/tmp/.");
cid->mutable_cxx()->add_cxx_system_include_paths("/usr/local/include");
cid->mutable_cxx()->add_cxx_system_include_paths(
"/usr/lib/gcc/x86_64-linux-gnu/4.4.3/include");
cid->mutable_cxx()->add_cxx_system_include_paths(
"/usr/lib/gcc/x86_64-linux-gnu/4.4.3/include-fixed");
cid->mutable_cxx()->add_cxx_system_include_paths("/usr/include");
cid->set_found(true);
CxxCompilerInfo info(std::move(cid));
EXPECT_TRUE(info.DependsOnCwd("/tmp"));
EXPECT_FALSE(info.DependsOnCwd("/usr/src"));
}
}
TEST_F(CompilerInfoBuilderTest, FillFromCompilerOutputsShouldUseProperPath) {
std::vector<string> envs;
#ifdef _WIN32
const string clang = file::JoinPath(TestDir(), "clang.bat");
InstallReadCommandOutputFunc(ReadCommandOutputByRedirector);
envs.emplace_back("PATHEXT=" + GetEnv("PATHEXT"));
#else
const string clang = file::JoinPath(TestDir(), "clang");
InstallReadCommandOutputFunc(ReadCommandOutputByPopen);
#endif
std::vector<string> args = {
clang,
};
envs.emplace_back("PATH=" + GetEnv("PATH"));
std::unique_ptr<CompilerFlags> flags(CompilerFlagsParser::MustNew(args, "."));
std::unique_ptr<CompilerInfoData> data(
cts_collection_.Get(flags->type())
->BuildCompilerInfoData(*flags, clang, envs));
EXPECT_TRUE(data.get());
EXPECT_EQ(0, data->failed_at());
}
TEST_F(CompilerInfoBuilderTest, DependsOnCwdWithResource) {
TmpdirUtil tmpdir("is_cwd_relative");
tmpdir.CreateEmptyFile("asan_blacklist.txt");
{ // under cwd.
CompilerInfoData::ResourceInfo r_data;
CompilerInfoBuilder::ResourceInfoFromPath(
".", tmpdir.FullPath("asan_blacklist.txt"),
CompilerInfoData::CLANG_RESOURCE, &r_data);
std::unique_ptr<CompilerInfoData> cid(new CompilerInfoData);
cid->set_found(true);
cid->mutable_cxx();
*cid->add_resource() = r_data;
CxxCompilerInfo info(std::move(cid));
EXPECT_TRUE(info.DependsOnCwd(tmpdir.tmpdir()));
EXPECT_FALSE(info.DependsOnCwd("/nonexistent"));
}
{ // relative path file.
CompilerInfoData::ResourceInfo r_data;
CompilerInfoBuilder::ResourceInfoFromPath(
tmpdir.tmpdir(), "asan_blacklist.txt", CompilerInfoData::CLANG_RESOURCE,
&r_data);
std::unique_ptr<CompilerInfoData> cid(new CompilerInfoData);
cid->set_found(true);
cid->mutable_cxx();
*cid->add_resource() = r_data;
CxxCompilerInfo info(std::move(cid));
EXPECT_TRUE(info.DependsOnCwd(tmpdir.tmpdir()));
EXPECT_TRUE(info.DependsOnCwd("/nonexistent"));
}
}
#ifdef __linux__
// Checks we can take CompilerInfo from /usr/bin/gcc etc.
TEST_F(CompilerInfoBuilderTest, GccSmoke) {
InstallReadCommandOutputFunc(ReadCommandOutputByPopen);
// Assuming testcases[i][0] is a path to gcc.
const std::vector<std::vector<string>> testcases = {
{
"/usr/bin/gcc",
},
{"/usr/bin/gcc", "-xc"},
{"/usr/bin/gcc", "-xc++"},
{
"/usr/bin/g++",
},
{"/usr/bin/g++", "-xc"},
{"/usr/bin/g++", "-xc++"},
};
const std::vector<string> envs;
for (const auto& args : testcases) {
std::unique_ptr<CompilerFlags> flags(
CompilerFlagsParser::MustNew(args, "."));
CxxCompilerInfo compiler_info(
cts_collection_.Get(flags->type())
->BuildCompilerInfoData(*flags, args[0], envs));
EXPECT_FALSE(compiler_info.HasError());
}
}
#endif
// Checks we can take CompilerInfo from
// third_party/llvm-build/Release+Assets/bin/clang etc.
TEST_F(CompilerInfoBuilderTest, ClangSmoke) {
string source_root_path =
string(file::Dirname(file::Dirname(devtools_goma::GetMyDirectory())));
#ifdef _WIN32
InstallReadCommandOutputFunc(ReadCommandOutputByRedirector);
const std::vector<string> envs{
"PATH=" + GetEnv("PATH"), "PATHEXT=" + GetEnv("PATHEXT"),
};
#else
InstallReadCommandOutputFunc(ReadCommandOutputByPopen);
const std::vector<string> envs;
#endif
string clang_path = GetClangPath();
ASSERT_TRUE(!clang_path.empty());
const std::vector<std::vector<string>> testcases = {
{clang_path}, {clang_path, "-xc"}, {clang_path, "-xc++"},
};
for (const auto& args : testcases) {
std::unique_ptr<CompilerFlags> flags(
CompilerFlagsParser::MustNew(args, "."));
CxxCompilerInfo compiler_info(
cts_collection_.Get(flags->type())
->BuildCompilerInfoData(*flags, args[0], envs));
EXPECT_FALSE(compiler_info.HasError());
}
}
} // namespace devtools_goma