diff options
author | Oliver Reiche <oliver.reiche@huawei.com> | 2025-06-23 15:08:01 +0200 |
---|---|---|
committer | Oliver Reiche <oliver.reiche@huawei.com> | 2025-06-24 14:56:58 +0200 |
commit | b41c60fd8179fec987f158347111f650924aad47 (patch) | |
tree | 61f4addc0ff45fb5d65abe0807015417aae2b579 | |
parent | bbcc5977f49646941ac35060bb74a27eda5fbd76 (diff) | |
download | justbuild-b41c60fd8179fec987f158347111f650924aad47.tar.gz |
Test: Add test for API output path modes
-rw-r--r-- | test/buildtool/execution_api/bazel/bazel_api.test.cpp | 17 | ||||
-rw-r--r-- | test/buildtool/execution_api/common/api_test.hpp | 104 | ||||
-rw-r--r-- | test/buildtool/execution_api/local/local_api.test.cpp | 13 |
3 files changed, 134 insertions, 0 deletions
diff --git a/test/buildtool/execution_api/bazel/bazel_api.test.cpp b/test/buildtool/execution_api/bazel/bazel_api.test.cpp index bc147ef5..bfe32f83 100644 --- a/test/buildtool/execution_api/bazel/bazel_api.test.cpp +++ b/test/buildtool/execution_api/bazel/bazel_api.test.cpp @@ -225,3 +225,20 @@ TEST_CASE("BazelAPI: Collect file and directory symlinks", "[execution_api]") { storage_config.Get().CreateTypedTmpDir("test_space")}; TestSymlinkCollection(api_factory, remote_config->platform_properties); } + +TEST_CASE("BazelAPI: Run in different output path modes", "[execution_api]") { + auto storage_config = TestStorageConfig::Create(); + auto remote_config = TestRemoteConfig::ReadFromEnvironment(); + + REQUIRE(remote_config); + REQUIRE(remote_config->remote_address); + auto auth = TestAuthConfig::ReadFromEnvironment(); + REQUIRE(auth); + + FactoryApi api_factory{ + &*remote_config->remote_address, + &*auth, + storage_config.Get().hash_function, + storage_config.Get().CreateTypedTmpDir("test_space")}; + TestOutputPathModes(api_factory, remote_config->platform_properties); +} diff --git a/test/buildtool/execution_api/common/api_test.hpp b/test/buildtool/execution_api/common/api_test.hpp index 34fbb29a..7cdfe20e 100644 --- a/test/buildtool/execution_api/common/api_test.hpp +++ b/test/buildtool/execution_api/common/api_test.hpp @@ -29,6 +29,8 @@ #include <vector> #include "catch2/catch_test_macros.hpp" +#include "catch2/catch_tostring.hpp" +#include "catch2/generators/catch_generators_all.hpp" #include "fmt/core.h" #include "gsl/gsl" #include "src/buildtool/common/artifact.hpp" @@ -42,6 +44,7 @@ #include "src/buildtool/execution_api/common/execution_api.hpp" #include "src/buildtool/execution_api/common/execution_response.hpp" #include "src/buildtool/execution_api/local/config.hpp" +#include "src/buildtool/execution_api/local/local_api.hpp" #include "src/buildtool/execution_api/local/local_response.hpp" #include "src/buildtool/execution_engine/dag/dag.hpp" #include "src/buildtool/file_system/file_system_manager.hpp" @@ -860,4 +863,105 @@ TestRetrieveFileAndSymlinkWithSameContentToPath(ApiFactory const& api_factory, } } +[[nodiscard]] static inline auto TestOutputPathModes( + ApiFactory const& api_factory, + ExecProps const& props) { + auto api = api_factory(); + + auto force_legacy = GENERATE(false, true); + + DYNAMIC_SECTION("Separated output paths (legacy=" << force_legacy << ")") { + auto action = + api->CreateAction(*api->UploadTree({}), + {"/bin/sh", + "-c", + "set -e; touch foo; ln -s none fox; " + "mkdir -p bar; rm -rf bat; ln -s none bat"}, + "", + {"foo", "fox"}, + {"bar", "bat"}, + {}, + props, + force_legacy); + REQUIRE(action); + + // run execution + auto const response = action->Execute(); + REQUIRE(response); + + // verify result + auto const artifacts = response->Artifacts(); + REQUIRE(artifacts.has_value()); + REQUIRE(artifacts.value()->contains("foo")); + CHECK(IsFileObject(artifacts.value()->at("foo").type)); + REQUIRE(artifacts.value()->contains("fox")); + CHECK(IsSymlinkObject(artifacts.value()->at("fox").type)); + REQUIRE(artifacts.value()->contains("bar")); + CHECK(IsTreeObject(artifacts.value()->at("bar").type)); + REQUIRE(artifacts.value()->contains("bat")); + CHECK(IsSymlinkObject(artifacts.value()->at("bat").type)); + + // verify DirectorySymlinks + auto* local_response = dynamic_cast<LocalResponse*>(response.get()); + if (local_response != nullptr) { + auto dir_symlinks = local_response->DirectorySymlinks(); + if (force_legacy or ProtocolTraits::IsNative(api->GetHashType())) { + // in legacy mode (<RBEv2.1), dir symlinks must be available, + // which is implicitly enabled for the native protocol as well. + REQUIRE(dir_symlinks.has_value()); + CHECK(*dir_symlinks != nullptr); + } + if (dir_symlinks and *dir_symlinks != nullptr) { + // even in non-legacy mode, the API is free to additionally + // report output directory symlinks, and if it does so, it must + // correctly report all output directory symlinks. + CHECK((*dir_symlinks)->contains("bat")); + } + } + } + + SECTION("Combined output paths") { + auto const* local_api = dynamic_cast<LocalApi const*>(api.get()); + if (local_api == nullptr) { + // skip: combined output paths are only available for local api + return; + } + + auto action = local_api->CreateAction( + *local_api->UploadTree({}), + {"/bin/sh", + "-c", + "set -e; touch foo; ln -s none fox; " + "mkdir -p bar; rm -rf bat; ln -s none bat"}, + "", + {"foo", "fox", "bar", "bat"}, + {}, + props); + REQUIRE(action); + + // run execution + auto const response = action->Execute(); + REQUIRE(response); + + // verify result + auto const artifacts = response->Artifacts(); + REQUIRE(artifacts.has_value()); + REQUIRE(artifacts.value()->contains("foo")); + CHECK(IsFileObject(artifacts.value()->at("foo").type)); + REQUIRE(artifacts.value()->contains("fox")); + CHECK(IsSymlinkObject(artifacts.value()->at("fox").type)); + REQUIRE(artifacts.value()->contains("bar")); + CHECK(IsTreeObject(artifacts.value()->at("bar").type)); + REQUIRE(artifacts.value()->contains("bat")); + CHECK(IsSymlinkObject(artifacts.value()->at("bat").type)); + + // with combined output paths, we cannot report output dir symlinks + auto* local_response = dynamic_cast<LocalResponse*>(response.get()); + if (local_response != nullptr) { + auto dir_symlinks = local_response->DirectorySymlinks(); + REQUIRE_FALSE(dir_symlinks); + } + } +} + #endif // INCLUDED_SRC_TEST_BUILDTOOL_EXECUTION_API_COMMON_API_TEST_HPP diff --git a/test/buildtool/execution_api/local/local_api.test.cpp b/test/buildtool/execution_api/local/local_api.test.cpp index 94b9bf75..5904eb4f 100644 --- a/test/buildtool/execution_api/local/local_api.test.cpp +++ b/test/buildtool/execution_api/local/local_api.test.cpp @@ -159,3 +159,16 @@ TEST_CASE("LocalAPI: Collect file and directory symlinks", "[execution_api]") { TestSymlinkCollection(api_factory, {}); } + +TEST_CASE("LocalAPI: Run in different output path modes", "[execution_api]") { + auto const storage_config = TestStorageConfig::Create(); + auto const storage = Storage::Create(&storage_config.Get()); + auto const local_exec_config = CreateLocalExecConfig(); + // pack the local context instances to be passed to LocalApi + LocalContext const local_context{.exec_config = &local_exec_config, + .storage_config = &storage_config.Get(), + .storage = &storage}; + FactoryApi api_factory(&local_context); + + TestOutputPathModes(api_factory, {}); +} |