| // 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 "gcc_compiler_info_builder.h" |
| |
| #include "gtest/gtest.h" |
| #include "mypath.h" |
| #include "path.h" |
| #include "unittest_util.h" |
| |
| namespace devtools_goma { |
| |
| class GCCCompilerInfoBuilderTest : 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 string parent_dir = file::JoinPath(GetMyDirectory(), ".."); |
| const string top_dir = file::JoinPath(parent_dir, ".."); |
| return file::JoinPath(top_dir, "test"); |
| } |
| }; |
| |
| TEST_F(GCCCompilerInfoBuilderTest, RewriteHashUnlockedEmptyRule) { |
| std::map<string, string> rule; |
| CompilerInfoData data; |
| auto* sub = data.add_subprograms(); |
| sub->set_hash("dummy_hash"); |
| EXPECT_FALSE(GCCCompilerInfoBuilder::RewriteHashUnlocked(rule, &data)); |
| EXPECT_EQ(1, data.subprograms_size()); |
| EXPECT_EQ("dummy_hash", data.subprograms(0).hash()); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, RewriteHashUnlockedNoMatchingRule) { |
| std::map<string, string> rule; |
| ASSERT_TRUE(rule.insert(std::make_pair("no_match", "no_match")).second); |
| CompilerInfoData data; |
| auto* sub = data.add_subprograms(); |
| sub->set_hash("dummy_hash"); |
| EXPECT_FALSE(GCCCompilerInfoBuilder::RewriteHashUnlocked(rule, &data)); |
| EXPECT_EQ(1, data.subprograms_size()); |
| EXPECT_EQ("dummy_hash", data.subprograms(0).hash()); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, RewriteHashUnlockedMatchingRule) { |
| std::map<string, string> rule; |
| ASSERT_TRUE(rule.insert(std::make_pair("old_hash", "new_hash")).second); |
| CompilerInfoData data; |
| auto* sub = data.add_subprograms(); |
| sub->set_hash("old_hash"); |
| EXPECT_TRUE(GCCCompilerInfoBuilder::RewriteHashUnlocked(rule, &data)); |
| EXPECT_EQ(1, data.subprograms_size()); |
| EXPECT_EQ("new_hash", data.subprograms(0).hash()); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, |
| RewriteHashUnlockedBothMatchingAndNotMatching) { |
| std::map<string, string> rule; |
| ASSERT_TRUE(rule.insert(std::make_pair("old_hash", "new_hash")).second); |
| CompilerInfoData data; |
| auto* sub = data.add_subprograms(); |
| sub->set_hash("old_hash"); |
| auto* sub2 = data.add_subprograms(); |
| sub2->set_hash("yet_another_hash"); |
| EXPECT_TRUE(GCCCompilerInfoBuilder::RewriteHashUnlocked(rule, &data)); |
| EXPECT_EQ(2, data.subprograms_size()); |
| EXPECT_EQ("new_hash", data.subprograms(0).hash()); |
| EXPECT_EQ("yet_another_hash", data.subprograms(1).hash()); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetExtraSubprogramsClangPlugin) { |
| const string cwd("/"); |
| |
| TmpdirUtil tmpdir("get_extra_subprograms_clang_plugin"); |
| tmpdir.SetCwd(cwd); |
| tmpdir.CreateEmptyFile("libPlugin.so"); |
| |
| std::vector<string> args, envs; |
| args.push_back("/usr/bin/clang"); |
| args.push_back("-Xclang"); |
| args.push_back("-load"); |
| args.push_back("-Xclang"); |
| args.push_back(file::JoinPath(tmpdir.tmpdir(), "libPlugin.so")); |
| args.push_back("-c"); |
| args.push_back("hello.c"); |
| GCCFlags flags(args, cwd); |
| std::vector<string> clang_plugins; |
| std::vector<string> B_options; |
| bool no_integrated_as = false; |
| GCCCompilerInfoBuilder::ParseSubprogramFlags( |
| "/usr/bin/clang", flags, &clang_plugins, &B_options, &no_integrated_as); |
| std::vector<string> expected = {tmpdir.FullPath("libPlugin.so")}; |
| EXPECT_EQ(expected, clang_plugins); |
| EXPECT_TRUE(B_options.empty()); |
| EXPECT_FALSE(no_integrated_as); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetExtraSubprogramsClangPluginRelative) { |
| const string cwd("/"); |
| |
| TmpdirUtil tmpdir("get_extra_subprograms_clang_plugin"); |
| tmpdir.SetCwd(cwd); |
| tmpdir.CreateEmptyFile("libPlugin.so"); |
| |
| std::vector<string> args, envs; |
| args.push_back("/usr/bin/clang"); |
| args.push_back("-Xclang"); |
| args.push_back("-load"); |
| args.push_back("-Xclang"); |
| args.push_back("libPlugin.so"); |
| args.push_back("-c"); |
| args.push_back("hello.c"); |
| GCCFlags flags(args, cwd); |
| std::vector<string> clang_plugins; |
| std::vector<string> B_options; |
| bool no_integrated_as = false; |
| GCCCompilerInfoBuilder::ParseSubprogramFlags( |
| "/usr/bin/clang", flags, &clang_plugins, &B_options, &no_integrated_as); |
| std::vector<string> expected = {"libPlugin.so"}; |
| EXPECT_EQ(expected, clang_plugins); |
| EXPECT_TRUE(B_options.empty()); |
| EXPECT_FALSE(no_integrated_as); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetExtraSubprogramsBOptions) { |
| const string cwd("/"); |
| |
| TmpdirUtil tmpdir("get_extra_subprograms_clang_plugin"); |
| tmpdir.SetCwd(cwd); |
| tmpdir.CreateEmptyFile("libPlugin.so"); |
| |
| std::vector<string> args, envs; |
| args.push_back("/usr/bin/clang"); |
| args.push_back("-B"); |
| args.push_back("dummy"); |
| args.push_back("-c"); |
| args.push_back("hello.c"); |
| GCCFlags flags(args, cwd); |
| std::vector<string> clang_plugins; |
| std::vector<string> B_options; |
| bool no_integrated_as = false; |
| GCCCompilerInfoBuilder::ParseSubprogramFlags( |
| "/usr/bin/clang", flags, &clang_plugins, &B_options, &no_integrated_as); |
| std::vector<string> expected = {"dummy"}; |
| EXPECT_TRUE(clang_plugins.empty()); |
| EXPECT_EQ(expected, B_options); |
| EXPECT_FALSE(no_integrated_as); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetCompilerNameUsualCases) { |
| std::vector<std::pair<string, string>> test_cases = { |
| {"clang", "clang"}, {"clang++", "clang"}, {"g++", "g++"}, {"gcc", "gcc"}, |
| }; |
| |
| GCCCompilerInfoBuilder builder; |
| for (const auto& tc : test_cases) { |
| CompilerInfoData data; |
| data.set_local_compiler_path(tc.first); |
| data.set_real_compiler_path(tc.second); |
| EXPECT_EQ(tc.first, builder.GetCompilerName(data)); |
| } |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetCompilerNameCc) { |
| std::vector<string> test_cases = {"clang", "gcc"}; |
| |
| GCCCompilerInfoBuilder builder; |
| for (const auto& tc : test_cases) { |
| CompilerInfoData data; |
| data.set_local_compiler_path("cc"); |
| data.set_real_compiler_path(tc); |
| EXPECT_EQ(tc, builder.GetCompilerName(data)); |
| } |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetCompilerNameCxx) { |
| GCCCompilerInfoBuilder builder; |
| CompilerInfoData data; |
| |
| data.set_local_compiler_path("c++"); |
| data.set_real_compiler_path("g++"); |
| EXPECT_EQ("g++", builder.GetCompilerName(data)); |
| |
| data.set_local_compiler_path("c++"); |
| data.set_real_compiler_path("clang"); |
| EXPECT_EQ("clang++", builder.GetCompilerName(data)); |
| } |
| |
| TEST_F(GCCCompilerInfoBuilderTest, GetCompilerNameUnsupportedCase) { |
| GCCCompilerInfoBuilder builder; |
| |
| CompilerInfoData data; |
| data.set_local_compiler_path("c++"); |
| data.set_real_compiler_path("clang++"); |
| EXPECT_EQ("", builder.GetCompilerName(data)); |
| } |
| |
| } // namespace devtools_goma |