| // Copyright 2016 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 <limits.h> |
| |
| #include <glog/logging.h> |
| #include <glog/stl_logging.h> |
| #include <gtest/gtest.h> |
| #include <json/json.h> |
| |
| #include "compilation_database_reader.h" |
| #include "file_dir.h" |
| #include "file_helper.h" |
| #include "path.h" |
| #include "unittest_util.h" |
| |
| using std::string; |
| |
| namespace devtools_goma { |
| |
| class CompilationDatabaseReaderTest : public testing::Test { |
| protected: |
| static bool AddCompileOptions(const std::string& source, |
| const std::string& db_path, |
| std::vector<std::string>* clang_args, |
| string* build_dir) { |
| return CompilationDatabaseReader::AddCompileOptions( |
| source, db_path, clang_args, build_dir); |
| } |
| |
| static bool MakeClangArgsFromCommandLine( |
| bool seen_hyphen_hyphen, |
| const std::vector<string>& args_after_hyphen_hyphen, |
| const string& input_file, |
| const string& cwd, |
| const string& build_path, |
| const std::vector<string>& extra_arg, |
| const std::vector<string>& extra_arg_before, |
| const string& compdb_path, |
| std::vector<string>* clang_args, |
| string* build_dir) { |
| return CompilationDatabaseReader::MakeClangArgsFromCommandLine( |
| seen_hyphen_hyphen, args_after_hyphen_hyphen, input_file, cwd, |
| build_path, extra_arg, extra_arg_before, compdb_path, clang_args, |
| build_dir); |
| } |
| |
| static string MakeCompilationDatabaseContent(const string& directory, |
| const string& command, |
| const string& file) { |
| Json::Value comp; |
| comp["directory"] = directory; |
| comp["command"] = command; |
| comp["file"] = file; |
| |
| Json::Value root; |
| root.append(comp); |
| |
| Json::FastWriter writer; |
| return writer.write(root); |
| } |
| }; |
| |
| TEST_F(CompilationDatabaseReaderTest, FindCompilationDatabase) { |
| TmpdirUtil tmpdir("compdb_unittest_fcd"); |
| tmpdir.SetCwd("/"); |
| |
| string ab_rel = file::JoinPath("a", "b"); |
| string ab_abs = tmpdir.FullPath(ab_rel); |
| |
| string compdb_content = MakeCompilationDatabaseContent( |
| ab_abs, |
| "clang -IA -IB -c foo.cc", |
| "foo.cc"); |
| |
| // The following directories and file are created. |
| // /a/b/ |
| // /c/d/ |
| // /compile_commands.json |
| |
| tmpdir.MkdirForPath(ab_rel, true); |
| tmpdir.MkdirForPath(file::JoinPath("c", "d"), true); |
| tmpdir.CreateTmpFile(file::JoinPath("c", "compile_commands.json"), |
| compdb_content); |
| |
| const string c_abs = tmpdir.FullPath("c"); |
| const string cd_abs = tmpdir.FullPath(file::JoinPath("c", "d")); |
| const string expected_compdb_path = |
| file::JoinPath(c_abs, "compile_commands.json"); |
| |
| // Set build_path is /c, first input file dir is /a/b |
| { |
| string compdb_path = |
| CompilationDatabaseReader::FindCompilationDatabase(c_abs, ab_abs); |
| EXPECT_EQ(expected_compdb_path, compdb_path); |
| } |
| |
| // Set build_path is empty, first input file dir is /c/d. |
| { |
| string compdb_path = |
| CompilationDatabaseReader::FindCompilationDatabase(string(), cd_abs); |
| EXPECT_EQ(expected_compdb_path, compdb_path); |
| } |
| |
| // Set build_path id /c/d, first input file dir is /a/b. |
| // Since we shouldn't search ancestor directory of build_path, |
| // compilation database should not be found. |
| { |
| string dbpath = |
| CompilationDatabaseReader::FindCompilationDatabase(cd_abs, ab_abs); |
| EXPECT_TRUE(dbpath.empty()); |
| } |
| } |
| |
| TEST_F(CompilationDatabaseReaderTest, WithCompilationDatabase) { |
| TmpdirUtil tmpdir("compdb_unittest"); |
| tmpdir.SetCwd("/"); |
| |
| // Make the following directories and files, and move cwd to /a/b. |
| // /a/b/ |
| // /compile_commands.json |
| |
| string ab_rel = file::JoinPath("a", "b"); |
| string ab_abs = tmpdir.FullPath(ab_rel); |
| |
| tmpdir.MkdirForPath(ab_rel, true); |
| |
| string compdb_content = MakeCompilationDatabaseContent( |
| ab_abs, |
| "clang -IA -IB -c foo.cc", |
| "foo.cc"); |
| tmpdir.CreateTmpFile("compile_commands.json", compdb_content); |
| |
| string compile_commands_json = tmpdir.FullPath("compile_commands.json"); |
| |
| string dbpath = |
| CompilationDatabaseReader::FindCompilationDatabase("", ab_abs); |
| EXPECT_EQ(compile_commands_json, dbpath); |
| |
| tmpdir.SetCwd(ab_rel); |
| string foo_path = tmpdir.FullPath("foo.cc"); |
| |
| std::vector<string> clang_args { |
| "clang++", |
| }; |
| string build_dir; |
| EXPECT_TRUE(AddCompileOptions(foo_path, dbpath, &clang_args, &build_dir)); |
| |
| std::vector<string> expected_clang_args { |
| "clang++", "-IA", "-IB", "-c", "foo.cc" |
| }; |
| EXPECT_EQ(expected_clang_args, clang_args); |
| EXPECT_EQ(ab_abs, build_dir); |
| } |
| |
| TEST_F(CompilationDatabaseReaderTest, WithCompilationDatabaseHavingGomaCC) { |
| TmpdirUtil tmpdir("compdb_unittest"); |
| tmpdir.SetCwd("/"); |
| |
| // Make the following directories and files, and move cwd to /a/b. |
| // /a/b/ |
| // /compile_commands.json |
| |
| string ab_rel = file::JoinPath("a", "b"); |
| string ab_abs = tmpdir.FullPath(ab_rel); |
| |
| tmpdir.MkdirForPath(ab_rel, true); |
| |
| string compdb_content = MakeCompilationDatabaseContent( |
| ab_abs, |
| "/home/goma/goma/gomacc clang -IA -IB -c foo.cc", |
| "foo.cc"); |
| tmpdir.CreateTmpFile("compile_commands.json", compdb_content); |
| |
| string compile_commands_json = tmpdir.FullPath("compile_commands.json"); |
| |
| string dbpath = |
| CompilationDatabaseReader::FindCompilationDatabase("", ab_abs); |
| EXPECT_EQ(compile_commands_json, dbpath); |
| |
| tmpdir.SetCwd(ab_rel); |
| string foo_path = tmpdir.FullPath("foo.cc"); |
| |
| std::vector<string> clang_args { |
| "clang++", |
| }; |
| string build_dir; |
| EXPECT_TRUE(AddCompileOptions(foo_path, dbpath, &clang_args, &build_dir)); |
| |
| std::vector<string> expected_clang_args { |
| "clang++", "-IA", "-IB", "-c", "foo.cc" |
| }; |
| EXPECT_EQ(expected_clang_args, clang_args); |
| EXPECT_EQ(ab_abs, build_dir); |
| } |
| |
| TEST_F(CompilationDatabaseReaderTest, |
| WithCompilationDatabaseHavingGomaCCCapitalCaseWithExtension) { |
| TmpdirUtil tmpdir("compdb_unittest"); |
| tmpdir.SetCwd("/"); |
| |
| // Make the following directories and files, and move cwd to /a/b. |
| // /a/b/ |
| // /compile_commands.json |
| |
| string ab_rel = file::JoinPath("a", "b"); |
| string ab_abs = tmpdir.FullPath(ab_rel); |
| |
| tmpdir.MkdirForPath(ab_rel, true); |
| |
| string compdb_content = MakeCompilationDatabaseContent( |
| ab_abs, |
| "/home/goma/goma/GOMACC.exe clang -IA -IB -c foo.cc", |
| "foo.cc"); |
| tmpdir.CreateTmpFile("compile_commands.json", compdb_content); |
| |
| string compile_commands_json = tmpdir.FullPath("compile_commands.json"); |
| |
| string dbpath = |
| CompilationDatabaseReader::FindCompilationDatabase("", ab_abs); |
| EXPECT_EQ(compile_commands_json, dbpath); |
| |
| tmpdir.SetCwd(ab_rel); |
| string foo_path = tmpdir.FullPath("foo.cc"); |
| |
| std::vector<string> clang_args { |
| "clang++", |
| }; |
| string build_dir; |
| EXPECT_TRUE(AddCompileOptions(foo_path, dbpath, &clang_args, &build_dir)); |
| |
| std::vector<string> expected_clang_args { |
| "clang++", "-IA", "-IB", "-c", "foo.cc" |
| }; |
| EXPECT_EQ(expected_clang_args, clang_args); |
| EXPECT_EQ(ab_abs, build_dir); |
| } |
| |
| TEST_F(CompilationDatabaseReaderTest, WithoutCompilationDatabase) { |
| std::vector<string> args_after_hyphen_hyphen { "-IA", "-IB" }; |
| string cwd = "/"; |
| std::vector<string> extra_arg { "-IC" }; |
| std::vector<string> extra_arg_before { "-ID" }; |
| |
| std::vector<string> clang_args { "clang" }; |
| string build_dir; |
| EXPECT_TRUE(MakeClangArgsFromCommandLine(true, args_after_hyphen_hyphen, |
| "foo.cc", cwd, "", extra_arg, |
| extra_arg_before, |
| "", &clang_args, &build_dir)); |
| |
| std::vector<string> expected_clang_args { |
| "clang", "-ID", "-IA", "-IB", "-IC", "-c", "foo.cc" |
| }; |
| |
| EXPECT_EQ(expected_clang_args, clang_args); |
| EXPECT_EQ(cwd, build_dir); |
| } |
| |
| } // namespace devtools_goma |