blob: c648db7302a476752d9f0ababdc41371ab225a5f [file] [log] [blame]
// 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