diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/buildtool/execution_api/bazel/TARGETS | 15 | ||||
-rw-r--r-- | test/buildtool/execution_api/bazel/bazel_api.test.cpp | 35 | ||||
-rw-r--r-- | test/buildtool/execution_api/common/TARGETS | 12 | ||||
-rw-r--r-- | test/buildtool/execution_api/common/api_test.hpp | 314 | ||||
-rw-r--r-- | test/buildtool/execution_api/local/TARGETS | 4 | ||||
-rw-r--r-- | test/buildtool/execution_api/local/local_api.test.cpp | 286 |
6 files changed, 389 insertions, 277 deletions
diff --git a/test/buildtool/execution_api/bazel/TARGETS b/test/buildtool/execution_api/bazel/TARGETS index 74890977..5978f7be 100644 --- a/test/buildtool/execution_api/bazel/TARGETS +++ b/test/buildtool/execution_api/bazel/TARGETS @@ -72,6 +72,18 @@ ] , "stage": ["test", "buildtool", "execution_api", "bazel"] } +, "bazel_api": + { "type": ["@", "rules", "CC/test", "test"] + , "name": ["bazel_api"] + , "srcs": ["bazel_api.test.cpp"] + , "deps": + [ ["@", "catch2", "", "catch2"] + , ["test/utils", "catch-main-remote-execution"] + , ["src/buildtool/execution_api/remote", "bazel"] + , ["test/buildtool/execution_api/common", "api_test"] + ] + , "stage": ["test", "buildtool", "execution_api", "bazel"] + } , "TESTS": { "type": "install" , "tainted": ["test"] @@ -82,6 +94,7 @@ , "execution_client" , "msg_factory" , "network" + , "bazel_api" ] } -}
\ No newline at end of file +} diff --git a/test/buildtool/execution_api/bazel/bazel_api.test.cpp b/test/buildtool/execution_api/bazel/bazel_api.test.cpp new file mode 100644 index 00000000..18d08f7c --- /dev/null +++ b/test/buildtool/execution_api/bazel/bazel_api.test.cpp @@ -0,0 +1,35 @@ +#include <cstdlib> +#include <string> + +#include "catch2/catch.hpp" +#include "src/buildtool/execution_api/remote/bazel/bazel_api.hpp" +#include "src/buildtool/execution_api/remote/config.hpp" +#include "test/buildtool/execution_api/common/api_test.hpp" +#include "test/utils/test_env.hpp" + +namespace { + +auto api_factory = []() { + static auto const& server = RemoteExecutionConfig::Instance(); + return IExecutionApi::Ptr{ + new BazelApi{"remote-execution", server.Host(), server.Port(), {}}}; +}; + +} // namespace + +TEST_CASE("BazelAPI: No input, no output", "[execution_api]") { + TestNoInputNoOutput(api_factory, ReadPlatformPropertiesFromEnv()); +} + +TEST_CASE("BazelAPI: No input, create output", "[execution_api]") { + TestNoInputCreateOutput(api_factory, ReadPlatformPropertiesFromEnv()); +} + +TEST_CASE("BazelAPI: One input copied to output", "[execution_api]") { + TestOneInputCopiedToOutput(api_factory, ReadPlatformPropertiesFromEnv()); +} + +TEST_CASE("BazelAPI: Non-zero exit code, create output", "[execution_api]") { + TestNonZeroExitCodeCreateOutput(api_factory, + ReadPlatformPropertiesFromEnv()); +} diff --git a/test/buildtool/execution_api/common/TARGETS b/test/buildtool/execution_api/common/TARGETS new file mode 100644 index 00000000..21095882 --- /dev/null +++ b/test/buildtool/execution_api/common/TARGETS @@ -0,0 +1,12 @@ +{ "api_test": + { "type": ["@", "rules", "CC", "library"] + , "name": ["api_test"] + , "hdrs": ["api_test.hpp"] + , "deps": + [ ["@", "catch2", "", "catch2"] + , ["src/buildtool/common", "artifact_factory"] + , ["src/buildtool/execution_api/common", "common"] + ] + , "stage": ["test", "buildtool", "execution_api", "common"] + } +} diff --git a/test/buildtool/execution_api/common/api_test.hpp b/test/buildtool/execution_api/common/api_test.hpp new file mode 100644 index 00000000..42026563 --- /dev/null +++ b/test/buildtool/execution_api/common/api_test.hpp @@ -0,0 +1,314 @@ +#include <cstdlib> +#include <string> + +#include "catch2/catch.hpp" +#include "src/buildtool/common/artifact_factory.hpp" +#include "src/buildtool/execution_api/common/execution_action.hpp" +#include "src/buildtool/execution_api/common/execution_api.hpp" +#include "src/buildtool/execution_api/common/execution_response.hpp" + +using ApiFactory = std::function<IExecutionApi::Ptr()>; +using ExecProps = std::map<std::string, std::string>; + +[[nodiscard]] static inline auto TestNoInputNoOutput( + ApiFactory const& api_factory, + ExecProps const& props, + bool is_hermetic = false) { + std::string test_content("test"); + + auto api = api_factory(); + + auto action = api->CreateAction( + *api->UploadTree({}), {"echo", "-n", test_content}, {}, {}, {}, props); + + SECTION("Cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->HasStdOut()); + CHECK(response->StdOut() == test_content); + + if (is_hermetic) { + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify caching") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->HasStdOut()); + CHECK(response->StdOut() == test_content); + CHECK(response->IsCached()); + } + } + } + + SECTION("Do not cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->HasStdOut()); + CHECK(response->StdOut() == test_content); + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify caching") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->HasStdOut()); + CHECK(response->StdOut() == test_content); + CHECK(not response->IsCached()); + } + } +} + +[[nodiscard]] static inline auto TestNoInputCreateOutput( + ApiFactory const& api_factory, + ExecProps const& props, + bool is_hermetic = false) { + std::string test_content("test"); + auto test_digest = ArtifactDigest::Create(test_content); + + std::string output_path{"output_file"}; + + auto api = api_factory(); + + auto action = api->CreateAction( + *api->UploadTree({}), + {"/bin/sh", + "-c", + "set -e\necho -n " + test_content + " > " + output_path}, + {output_path}, + {}, + {}, + props); + + SECTION("Cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + + if (is_hermetic) { + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify caching") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(response->IsCached()); + } + } + } + + SECTION("Do not cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify caching") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + } + } +} + +[[nodiscard]] static inline auto TestOneInputCopiedToOutput( + ApiFactory const& api_factory, + ExecProps const& props, + bool is_hermetic = false) { + std::string test_content("test"); + auto test_digest = ArtifactDigest::Create(test_content); + + auto input_artifact_opt = + ArtifactFactory::FromDescription(ArtifactFactory::DescribeKnownArtifact( + test_digest.hash(), test_digest.size(), ObjectType::File)); + CHECK(input_artifact_opt.has_value()); + auto input_artifact = + DependencyGraph::ArtifactNode{std::move(*input_artifact_opt)}; + + std::string input_path{"dir/subdir/input"}; + std::string output_path{"output_file"}; + + auto api = api_factory(); + CHECK(api->Upload(BlobContainer{{BazelBlob{test_digest, test_content}}}, + false)); + + auto action = + api->CreateAction(*api->UploadTree({{input_path, &input_artifact}}), + {"cp", input_path, output_path}, + {output_path}, + {}, + {}, + props); + + SECTION("Cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + + if (is_hermetic) { + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify caching") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(response->IsCached()); + } + } + } + + SECTION("Do not cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify caching") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + } + } +} + +[[nodiscard]] static inline auto TestNonZeroExitCodeCreateOutput( + ApiFactory const& api_factory, + ExecProps const& props) { + std::string test_content("test"); + auto test_digest = ArtifactDigest::Create(test_content); + + std::string output_path{"output_file"}; + + auto api = api_factory(); + + auto action = api->CreateAction(*api->UploadTree({}), + {"/bin/sh", + "-c", + "set -e\necho -n " + test_content + " > " + + output_path + "\nexit 1\n"}, + {output_path}, + {}, + {}, + props); + + SECTION("Cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->ExitCode() == 1); + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify that non-zero actions are rerun") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->ExitCode() == 1); + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + } + } + + SECTION("Do not cache execution result in action cache") { + action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); + + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->ExitCode() == 1); + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + + SECTION("Rerun execution to verify non-zero actions are not cached") { + // run execution + auto response = action->Execute(); + REQUIRE(response); + + // verify result + CHECK(response->ExitCode() == 1); + auto artifacts = response->Artifacts(); + REQUIRE(artifacts.contains(output_path)); + CHECK(artifacts.at(output_path).digest == test_digest); + CHECK(not response->IsCached()); + } + } +} diff --git a/test/buildtool/execution_api/local/TARGETS b/test/buildtool/execution_api/local/TARGETS index 1a86621f..92107bd8 100644 --- a/test/buildtool/execution_api/local/TARGETS +++ b/test/buildtool/execution_api/local/TARGETS @@ -45,8 +45,8 @@ , "deps": [ ["@", "catch2", "", "catch2"] , ["test", "catch-main"] - , ["src/buildtool/common", "artifact_factory"] , ["src/buildtool/execution_api/local", "local"] + , ["test/buildtool/execution_api/common", "api_test"] , ["test/utils", "local_hermeticity"] ] , "stage": ["test", "buildtool", "execution_api", "local"] @@ -70,4 +70,4 @@ , "deps": ["local_ac", "local_api", "local_cas", "local_execution", "local_storage"] } -}
\ No newline at end of file +} diff --git a/test/buildtool/execution_api/local/local_api.test.cpp b/test/buildtool/execution_api/local/local_api.test.cpp index 39eaa6f0..e347c445 100644 --- a/test/buildtool/execution_api/local/local_api.test.cpp +++ b/test/buildtool/execution_api/local/local_api.test.cpp @@ -1,299 +1,37 @@ +#include <cstdlib> #include <string> #include "catch2/catch.hpp" -#include "src/buildtool/common/artifact_factory.hpp" -#include "src/buildtool/execution_api/common/execution_action.hpp" -#include "src/buildtool/execution_api/common/execution_api.hpp" -#include "src/buildtool/execution_api/common/execution_response.hpp" #include "src/buildtool/execution_api/local/local_api.hpp" +#include "test/buildtool/execution_api/common/api_test.hpp" #include "test/utils/hermeticity/local.hpp" -TEST_CASE_METHOD(HermeticLocalTestFixture, - "LocalAPI: No input, no output", - "[execution_api]") { - std::string test_content("test"); - - auto api = LocalApi(); - - auto action = api.CreateAction( - *api.UploadTree({}), {"echo", "-n", test_content}, {}, {}, {}, {}); - - SECTION("Cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); +namespace { - // verify result - CHECK(response->HasStdOut()); - CHECK(response->StdOut() == test_content); - CHECK(not response->IsCached()); +auto api_factory = []() { return IExecutionApi::Ptr{new LocalApi()}; }; - SECTION("Rerun execution to verify caching") { - // run execution - auto response = action->Execute(); - REQUIRE(response); +} // namespace - // verify result - CHECK(response->HasStdOut()); - CHECK(response->StdOut() == test_content); - CHECK(response->IsCached()); - } - } - - SECTION("Do not cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - CHECK(response->HasStdOut()); - CHECK(response->StdOut() == test_content); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify caching") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - CHECK(response->HasStdOut()); - CHECK(response->StdOut() == test_content); - CHECK(not response->IsCached()); - } - } +TEST_CASE_METHOD(HermeticLocalTestFixture, + "LocalAPI: No input, no output", + "[execution_api]") { + TestNoInputNoOutput(api_factory, {}, /*is_hermetic=*/true); } TEST_CASE_METHOD(HermeticLocalTestFixture, "LocalAPI: No input, create output", "[execution_api]") { - std::string test_content("test"); - auto test_digest = ArtifactDigest::Create(test_content); - - std::string output_path{"output_file"}; - - auto api = LocalApi(); - - auto action = api.CreateAction( - *api.UploadTree({}), - {"/bin/sh", - "-c", - "set -e\necho -n " + test_content + " > " + output_path}, - {output_path}, - {}, - {}, - {}); - - SECTION("Cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify caching") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(response->IsCached()); - } - } - - SECTION("Do not cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify caching") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - } - } + TestNoInputCreateOutput(api_factory, {}, /*is_hermetic=*/true); } TEST_CASE_METHOD(HermeticLocalTestFixture, "LocalAPI: One input copied to output", "[execution_api]") { - std::string test_content("test"); - auto test_digest = ArtifactDigest::Create(test_content); - - auto input_artifact_opt = - ArtifactFactory::FromDescription(ArtifactFactory::DescribeKnownArtifact( - test_digest.hash(), test_digest.size(), ObjectType::File)); - CHECK(input_artifact_opt.has_value()); - auto input_artifact = - DependencyGraph::ArtifactNode{std::move(*input_artifact_opt)}; - - std::string input_path{"dir/subdir/input"}; - std::string output_path{"output_file"}; - - auto api = LocalApi(); - CHECK(api.Upload(BlobContainer{{BazelBlob{test_digest, test_content}}}, - false)); - - auto action = - api.CreateAction(*api.UploadTree({{input_path, &input_artifact}}), - {"cp", input_path, output_path}, - {output_path}, - {}, - {}, - {}); - - SECTION("Cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify caching") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(response->IsCached()); - } - } - - SECTION("Do not cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify caching") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - } - } + TestOneInputCopiedToOutput(api_factory, {}, /*is_hermetic=*/true); } TEST_CASE_METHOD(HermeticLocalTestFixture, "LocalAPI: Non-zero exit code, create output", "[execution_api]") { - std::string test_content("test"); - auto test_digest = ArtifactDigest::Create(test_content); - - std::string output_path{"output_file"}; - - auto api = LocalApi(); - - auto action = api.CreateAction(*api.UploadTree({}), - {"/bin/sh", - "-c", - "set -e\necho -n " + test_content + " > " + - output_path + "\nexit 1\n"}, - {output_path}, - {}, - {}, - {}); - - SECTION("Cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::CacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - CHECK(response->ExitCode() == 1); - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify that non-zero actions are rerun") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - CHECK(response->ExitCode() == 1); - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - } - } - - SECTION("Do not cache execution result in action cache") { - action->SetCacheFlag(IExecutionAction::CacheFlag::DoNotCacheOutput); - - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - CHECK(response->ExitCode() == 1); - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - - SECTION("Rerun execution to verify non-zero actions are not cached") { - // run execution - auto response = action->Execute(); - REQUIRE(response); - - // verify result - CHECK(response->ExitCode() == 1); - auto artifacts = response->Artifacts(); - REQUIRE(artifacts.contains(output_path)); - CHECK(artifacts.at(output_path).digest == test_digest); - CHECK(not response->IsCached()); - } - } + TestNonZeroExitCodeCreateOutput(api_factory, {}); } |