blob: a941b389e6f48b63913f5625b6814581bcb86b98 [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 "compile_task.h"
#include <memory>
#include <set>
#include <string>
#include "absl/strings/ascii.h"
#include "compiler_flags.h"
#include "gtest/gtest.h"
#include "path.h"
namespace devtools_goma {
namespace {
const char kRootDir[] =
#ifdef _WIN32
"C:\\";
#else
"/";
#endif
} // anonymous namespace
class CompileTaskTest : public testing::Test {
public:
static bool IsLocalCompilerPathValid(
const string& trace_id,
const ExecReq& req,
const CompilerFlags* flags) {
return CompileTask::IsLocalCompilerPathValid(trace_id, req, flags);
}
static void RemoveDuplicateFiles(const std::string& cwd,
std::set<std::string>* filenames) {
CompileTask::RemoveDuplicateFiles(cwd, filenames);
}
};
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithEmptyLocalCompilerPath) {
ExecReq req;
req.mutable_command_spec()->set_name("gcc");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86_64-linux-gnu");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
std::vector<string> args = {"gcc", "-c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_TRUE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithSameCommandSpec) {
ExecReq req;
req.mutable_command_spec()->set_name("gcc");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86_64-linux-gnu");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("/usr/bin/gcc");
std::vector<string> args = {"gcc", "-c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_TRUE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithUnknownName) {
ExecReq req;
req.mutable_command_spec()->set_name("gcc");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86_64-linux-gnu");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("/usr/bin/id");
std::vector<string> args = {"gcc", "-c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_FALSE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithCommandSpecMismatch) {
ExecReq req;
req.mutable_command_spec()->set_name("clang");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86_64-linux-gnu");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("/usr/bin/gcc");
std::vector<string> args = {"gcc", "-c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_FALSE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithArgsMismatch) {
ExecReq req;
req.mutable_command_spec()->set_name("gcc");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86_64-linux-gnu");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("/usr/bin/gcc");
std::vector<string> args = {"clang", "-c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_FALSE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithSameCommandSpecClExe) {
ExecReq req;
req.mutable_command_spec()->set_name("cl.exe");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("c:\\dummy\\cl.exe");
std::vector<string> args = {"c:\\dummy\\cl.exe", "/c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_TRUE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithOmittingExtension) {
ExecReq req;
req.mutable_command_spec()->set_name("cl.exe");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("c:\\dummy\\cl");
std::vector<string> args = {"cl", "/c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_TRUE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithUnknownNameClExe) {
ExecReq req;
req.mutable_command_spec()->set_name("cl.exe");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path(
"c:\\dummy\\shutdown.exe");
std::vector<string> args = {"c:\\dummy\\cl.exe", "/c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_FALSE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithCommandSpecMismatchClExe) {
ExecReq req;
req.mutable_command_spec()->set_name("clang-cl");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("c:\\dummy\\cl.exe");
std::vector<string> args = {"c:\\dummy\\cl.exe", "/c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_FALSE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
TEST_F(CompileTaskTest, IsLocalCompilerPathValidWithArgsMismatchClExe) {
ExecReq req;
req.mutable_command_spec()->set_name("cl.exe");
req.mutable_command_spec()->set_version("1.2.3");
req.mutable_command_spec()->set_target("x86");
req.mutable_command_spec()->set_binary_hash("deadbeaf");
req.set_cwd("/tmp");
req.mutable_command_spec()->set_local_compiler_path("c:\\dummy\\cl.exe");
std::vector<string> args = {"c:\\dummy\\clang-cl.exe", "/c", "dummy.cc"};
std::unique_ptr<CompilerFlags> flag(CompilerFlags::New(args, "."));
EXPECT_FALSE(CompileTaskTest::IsLocalCompilerPathValid(
"dummy", req, flag.get()));
}
// TODO: add other combinations if necessary.
TEST_F(CompileTaskTest, RemoveDuplicateFiles) {
{
// different filepath
std::set<std::string> filenames {
file::JoinPath(kRootDir, "foo", "bar.cc"),
file::JoinPath(kRootDir, "foo", "baz.cc")
};
RemoveDuplicateFiles("", &filenames);
std::set<std::string> expected {
file::JoinPath(kRootDir, "foo", "bar.cc"),
file::JoinPath(kRootDir, "foo", "baz.cc")
};
EXPECT_EQ(filenames, expected);
}
{
// different filepath if case is not same.
std::set<std::string> filenames {
file::JoinPath(kRootDir, "Foo"),
file::JoinPath(absl::AsciiStrToLower(kRootDir), "fOO"),
};
RemoveDuplicateFiles("", &filenames);
std::set<std::string> expected {
file::JoinPath(kRootDir, "Foo"),
file::JoinPath(absl::AsciiStrToLower(kRootDir), "fOO"),
};
EXPECT_EQ(filenames, expected);
}
{
// same filepath when JoinPathRespectAbsolute
std::set<std::string> filenames {
"bar.cc", file::JoinPath(kRootDir, "foo", "bar.cc")};
RemoveDuplicateFiles(file::JoinPath(kRootDir, "foo"), &filenames);
std::set<std::string> expected {"bar.cc"};;
EXPECT_EQ(filenames, expected);
}
{
// same filepath when JoinPathRespectAbsolute with ..
std::set<std::string> filenames {
file::JoinPath("..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "baz", "..", "bar.cc")
};
RemoveDuplicateFiles(file::JoinPath(kRootDir, "foo", "baz"),
&filenames);
std::set<std::string> expected {file::JoinPath("..", "bar.cc")};
EXPECT_EQ(filenames, expected);
}
{
// different filepath when JoinPathRespectAbsolute
std::set<std::string> filenames {
file::JoinPath(kRootDir, "foo", "baz", "..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "bar.cc")
};
RemoveDuplicateFiles("", &filenames);
std::set<std::string> expected {
file::JoinPath(kRootDir, "foo", "baz", "..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "bar.cc")
};
EXPECT_EQ(filenames, expected);
}
{
// different filepath when JoinPathRespectAbsolute
std::set<std::string> filenames {
file::JoinPath("baz", "..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "bar.cc")
};
RemoveDuplicateFiles(file::JoinPath(kRootDir, "foo"), &filenames);
std::set<std::string> expected {
file::JoinPath("baz", "..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "bar.cc")
};
EXPECT_EQ(filenames, expected);
}
{
// different filepath when JoinPathRespectAbsolute
std::set<std::string> filenames {
file::JoinPath("..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "bar.cc")
};
RemoveDuplicateFiles(file::JoinPath(kRootDir, "foo", "baz"),
&filenames);
std::set<std::string> expected {
file::JoinPath("..", "bar.cc"),
file::JoinPath(kRootDir, "foo", "bar.cc")
};
EXPECT_EQ(filenames, expected);
}
}
} // namespace devtools_goma