summaryrefslogtreecommitdiff
path: root/test/buildtool/execution_api/local/local_execution.test.cpp
diff options
context:
space:
mode:
authorKlaus Aehlig <klaus.aehlig@huawei.com>2022-02-22 17:03:21 +0100
committerKlaus Aehlig <klaus.aehlig@huawei.com>2022-02-22 17:03:21 +0100
commit619def44c1cca9f3cdf63544d5f24f2c7a7d9b77 (patch)
tree01868de723cb82c86842f33743fa7b14e24c1fa3 /test/buildtool/execution_api/local/local_execution.test.cpp
downloadjustbuild-619def44c1cca9f3cdf63544d5f24f2c7a7d9b77.tar.gz
Initial self-hosting commit
This is the initial version of our tool that is able to build itself. In can be bootstrapped by ./bin/bootstrap.py Co-authored-by: Oliver Reiche <oliver.reiche@huawei.com> Co-authored-by: Victor Moreno <victor.moreno1@huawei.com>
Diffstat (limited to 'test/buildtool/execution_api/local/local_execution.test.cpp')
-rwxr-xr-xtest/buildtool/execution_api/local/local_execution.test.cpp274
1 files changed, 274 insertions, 0 deletions
diff --git a/test/buildtool/execution_api/local/local_execution.test.cpp b/test/buildtool/execution_api/local/local_execution.test.cpp
new file mode 100755
index 00000000..6c38c669
--- /dev/null
+++ b/test/buildtool/execution_api/local/local_execution.test.cpp
@@ -0,0 +1,274 @@
+#include <chrono>
+#include <string>
+#include <vector>
+
+#include "catch2/catch.hpp"
+#include "src/buildtool/common/artifact_factory.hpp"
+#include "src/buildtool/execution_api/local/local_api.hpp"
+#include "test/utils/hermeticity/local.hpp"
+
+namespace {
+
+[[nodiscard]] auto GetTestDir() -> std::filesystem::path {
+ auto* tmp_dir = std::getenv("TEST_TMPDIR");
+ if (tmp_dir != nullptr) {
+ return tmp_dir;
+ }
+ return FileSystemManager::GetCurrentDirectory() /
+ "test/buildtool/execution_api/local";
+}
+
+} // namespace
+
+TEST_CASE_METHOD(HermeticLocalTestFixture,
+ "LocalExecution: No input, no output",
+ "[execution_api]") {
+ auto api = LocalApi{};
+
+ std::string test_content("test");
+ std::vector<std::string> const cmdline = {"echo", "-n", test_content};
+ auto action =
+ api.CreateAction(*api.UploadTree({}), cmdline, {}, {}, {}, {});
+ REQUIRE(action);
+
+ SECTION("Cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ CHECK(output->StdOut() == test_content);
+
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK(output->IsCached());
+ }
+
+ SECTION("Do not cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ CHECK(output->StdOut() == test_content);
+
+ // ensure result IS STILL NOT in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK_FALSE(output->IsCached());
+ }
+}
+
+TEST_CASE_METHOD(HermeticLocalTestFixture,
+ "LocalExecution: No input, no output, env variables used",
+ "[execution_api]") {
+ auto api = LocalApi{};
+
+ std::string test_content("test from env var");
+ std::vector<std::string> const cmdline = {
+ "/bin/sh", "-c", "set -e\necho -n ${MYCONTENT}"};
+ auto action = api.CreateAction(*api.UploadTree({}),
+ cmdline,
+ {},
+ {},
+ {{"MYCONTENT", test_content}},
+ {});
+ REQUIRE(action);
+
+ SECTION("Cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ CHECK(output->StdOut() == test_content);
+
+ // ensure result IS in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK(output->IsCached());
+ }
+
+ SECTION("Do not cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ CHECK(output->StdOut() == test_content);
+
+ // ensure result IS STILL NOT in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK_FALSE(output->IsCached());
+ }
+}
+
+TEST_CASE_METHOD(HermeticLocalTestFixture,
+ "LocalExecution: No input, create output",
+ "[execution_api]") {
+ auto api = LocalApi{};
+
+ std::string test_content("test");
+ auto test_digest = ArtifactDigest::Create(test_content);
+
+ std::string output_path{"output_file"};
+ std::vector<std::string> const cmdline = {
+ "/bin/sh",
+ "-c",
+ "set -e\necho -n " + test_content + " > " + output_path};
+
+ auto action = api.CreateAction(
+ *api.UploadTree({}), cmdline, {output_path}, {}, {}, {});
+ REQUIRE(action);
+
+ SECTION("Cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ auto artifacts = output->Artifacts();
+ REQUIRE(artifacts.contains(output_path));
+ CHECK(artifacts.at(output_path).digest == test_digest);
+
+ // ensure result IS in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK(output->IsCached());
+ }
+
+ SECTION("Do not cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ auto artifacts = output->Artifacts();
+ REQUIRE(artifacts.contains(output_path));
+ CHECK(artifacts.at(output_path).digest == test_digest);
+
+ // ensure result IS STILL NOT in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK_FALSE(output->IsCached());
+ }
+}
+
+TEST_CASE_METHOD(HermeticLocalTestFixture,
+ "LocalExecution: One input copied to output",
+ "[execution_api]") {
+ auto api = LocalApi{};
+
+ std::string test_content("test");
+ auto test_digest = ArtifactDigest::Create(test_content);
+ REQUIRE(api.Upload(BlobContainer{{BazelBlob{test_digest, test_content}}},
+ false));
+
+ std::string input_path{"dir/subdir/input"};
+ std::string output_path{"output_file"};
+
+ std::vector<std::string> const cmdline = {"cp", input_path, output_path};
+
+ auto local_artifact_opt =
+ ArtifactFactory::FromDescription(ArtifactFactory::DescribeKnownArtifact(
+ test_digest.hash(), test_digest.size(), ObjectType::File));
+ REQUIRE(local_artifact_opt);
+ auto local_artifact =
+ DependencyGraph::ArtifactNode{std::move(*local_artifact_opt)};
+
+ auto action =
+ api.CreateAction(*api.UploadTree({{input_path, &local_artifact}}),
+ cmdline,
+ {output_path},
+ {},
+ {},
+ {});
+ REQUIRE(action);
+
+ SECTION("Cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ auto artifacts = output->Artifacts();
+ REQUIRE(artifacts.contains(output_path));
+ CHECK(artifacts.at(output_path).digest == test_digest);
+
+ // ensure result IS in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK(output->IsCached());
+ }
+
+ SECTION("Do not cache execution result in action cache") {
+ // run execution
+ action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput);
+ auto output = action->Execute(nullptr);
+ REQUIRE(output);
+
+ // verify result
+ CHECK_FALSE(output->IsCached());
+ auto artifacts = output->Artifacts();
+ REQUIRE(artifacts.contains(output_path));
+ CHECK(artifacts.at(output_path).digest == test_digest);
+
+ // ensure result IS STILL NOT in cache
+ output = action->Execute(nullptr);
+ REQUIRE(output);
+ CHECK_FALSE(output->IsCached());
+ }
+}
+
+TEST_CASE_METHOD(HermeticLocalTestFixture,
+ "LocalExecution: Cache failed action's result",
+ "[execution_api]") {
+ auto api = LocalApi{};
+
+ auto flag = GetTestDir() / "flag";
+ std::vector<std::string> const cmdline = {
+ "sh", "-c", fmt::format("[ -f '{}' ]", flag.string())};
+
+ auto action =
+ api.CreateAction(*api.UploadTree({}), cmdline, {}, {}, {}, {});
+ REQUIRE(action);
+
+ action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput);
+
+ // run failed action
+ auto failed = action->Execute(nullptr);
+ REQUIRE(failed);
+ CHECK_FALSE(failed->IsCached());
+ CHECK(failed->ExitCode() != 0);
+
+ REQUIRE(FileSystemManager::CreateFile(flag));
+
+ // run success action (should rerun and overwrite)
+ auto success = action->Execute(nullptr);
+ REQUIRE(success);
+ CHECK_FALSE(success->IsCached());
+ CHECK(success->ExitCode() == 0);
+
+ // rerun success action (should be served from cache)
+ auto cached = action->Execute(nullptr);
+ REQUIRE(cached);
+ CHECK(cached->IsCached());
+ CHECK(cached->ExitCode() == 0);
+
+ CHECK(FileSystemManager::RemoveFile(flag));
+}