1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
|
// Copyright 2024 Huawei Cloud Computing Technology Co., Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/buildtool/execution_api/execution_service/cas_server.hpp"
#include <functional>
#include <optional>
#include <string>
#include <utility>
#include <vector>
#include <grpcpp/support/status.h>
// Don't include "proto"
// IWYU pragma: no_include "build/bazel/remote/execution/v2/remote_execution.grpc.pb.h"
#include "catch2/catch_test_macros.hpp"
#include "gsl/gsl"
#include "src/buildtool/common/bazel_digest_factory.hpp"
#include "src/buildtool/common/bazel_types.hpp"
#include "src/buildtool/common/protocol_traits.hpp"
#include "src/buildtool/crypto/hash_function.hpp"
#include "src/buildtool/execution_api/local/config.hpp"
#include "src/buildtool/execution_api/local/context.hpp"
#include "src/buildtool/file_system/git_repo.hpp"
#include "src/buildtool/file_system/object_type.hpp"
#include "src/buildtool/storage/config.hpp"
#include "src/buildtool/storage/storage.hpp"
#include "test/utils/hermeticity/test_hash_function_type.hpp"
#include "test/utils/hermeticity/test_storage_config.hpp"
namespace {
[[nodiscard]] auto Upload(
gsl::not_null<bazel_re::ContentAddressableStorage::Service*> const&
cas_server,
std::string const& instance_name,
bazel_re::Digest const& digest,
std::string const& content) noexcept -> grpc::Status {
auto request = bazel_re::BatchUpdateBlobsRequest{};
request.set_instance_name(instance_name);
auto* req = request.add_requests();
req->mutable_digest()->CopyFrom(digest);
req->set_data(content);
auto response = bazel_re::BatchUpdateBlobsResponse{};
return cas_server->BatchUpdateBlobs(nullptr, &request, &response);
}
} // namespace
TEST_CASE("CAS Service: upload incomplete tree", "[execution_service]") {
// For compatible mode tree invariants aren't checked.
if (not ProtocolTraits::IsNative(TestHashType::ReadFromEnvironment())) {
return;
}
auto const storage_config = TestStorageConfig::Create();
auto const storage = Storage::Create(&storage_config.Get());
LocalExecutionConfig const local_exec_config{};
// pack the local context instances to be passed
LocalContext const local_context{.exec_config = &local_exec_config,
.storage_config = &storage_config.Get(),
.storage = &storage};
auto cas_server = CASServiceImpl{&local_context};
auto instance_name = std::string{"remote-execution"};
// Create an empty tree.
auto empty_entries = GitRepo::tree_entries_t{};
auto empty_tree = GitRepo::CreateShallowTree(empty_entries);
REQUIRE(empty_tree);
auto empty_tree_digest = BazelDigestFactory::HashDataAs<ObjectType::Tree>(
storage_config.Get().hash_function, empty_tree->second);
// Create a tree containing the empty tree.
auto entries = GitRepo::tree_entries_t{};
entries[empty_tree->first].emplace_back("empty_tree", ObjectType::Tree);
auto tree = GitRepo::CreateShallowTree(entries);
REQUIRE(tree);
auto tree_digest = BazelDigestFactory::HashDataAs<ObjectType::Tree>(
storage_config.Get().hash_function, tree->second);
// Upload tree. The tree invariant is violated, thus, a negative answer is
// expected.
auto status = Upload(&cas_server, instance_name, tree_digest, tree->second);
CHECK(not status.ok());
// Upload empty tree.
status = Upload(
&cas_server, instance_name, empty_tree_digest, empty_tree->second);
CHECK(status.ok());
// Upload tree again. This time, the tree invariant is honored and a
// positive answer is expected.
status = Upload(&cas_server, instance_name, tree_digest, tree->second);
CHECK(status.ok());
}
|