blob: 6e493d03c510a3eaa34cec570831925680a3e544 [file]
// Copyright 2026 Google LLC
//
// 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
//
// https://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 "formats/pdf/manifest_store_merger.h"
#include <string>
#include <utility>
#include <vector>
#include "absl/log/absl_check.h"
#include "absl/status/status.h"
#include "absl/status/status_matchers.h"
#include "absl/status/statusor.h"
#include "absl/strings/cord.h"
#include "absl/strings/string_view.h"
#include "constants/labels.h"
#include "gmock/gmock.h"
#include "gtest/gtest.h"
#include "jumbf/box.h"
#include "jumbf/box_builder.h"
#include "jumbf/constants.h"
#include "jumbf/encode_params.h"
#include "jumbf/parse.h"
#include "uuid/uuid.h"
namespace credentio {
namespace {
using ::absl_testing::IsOkAndHolds;
using ::absl_testing::StatusIs;
using ::credentio::kManifestStoreLabel;
using ::credentio::kManifestStoreUuid;
using ::credentio::kStandardManifestUuid;
using ::jumbf::DescriptionBoxOptions;
using ::jumbf::kCborBoxType;
using ::jumbf::SuperBox;
using ::jumbf::SuperBoxBuilder;
std::string CreateTestManifestStore(absl::string_view manifest_label,
absl::string_view payload_data) {
SuperBoxBuilder manifest_builder(
kStandardManifestUuid,
DescriptionBoxOptions{.requestable_iff_label = true,
.label = absl::Cord(manifest_label)});
ABSL_CHECK_OK(
manifest_builder.AddContent(kCborBoxType, absl::Cord(payload_data)));
absl::StatusOr<jumbf::BuiltSuperBox> manifest_box =
std::move(manifest_builder).Finalize();
ABSL_CHECK_OK(manifest_box);
SuperBoxBuilder store_builder(
kManifestStoreUuid,
DescriptionBoxOptions{.requestable_iff_label = true,
.label = absl::Cord(kManifestStoreLabel)});
ABSL_CHECK_OK(store_builder.AddChild(*std::move(manifest_box)));
absl::StatusOr<jumbf::BuiltSuperBox> store_box =
std::move(store_builder).Finalize();
ABSL_CHECK_OK(store_box);
return std::string(std::move(*store_box).AsCord());
}
TEST(ManifestStoreMergerTest, EmptyStoresListReturnsError) {
EXPECT_THAT(MergeManifestStores({}),
StatusIs(absl::StatusCode::kInvalidArgument));
}
TEST(ManifestStoreMergerTest, SingleStoreReturnedUnmodified) {
std::string store = CreateTestManifestStore("test_manifest", "data");
EXPECT_THAT(MergeManifestStores({store}), IsOkAndHolds(store));
}
TEST(ManifestStoreMergerTest, MultipleStoresMergedInCorrectOrder) {
std::string store1 = CreateTestManifestStore("manifest_1", "data_1");
std::string store2 = CreateTestManifestStore("manifest_2", "data_2");
absl::StatusOr<std::string> merged = MergeManifestStores({store1, store2});
ABSL_ASSERT_OK(merged);
absl::string_view view = *merged;
absl::StatusOr<SuperBox> superbox =
jumbf::ConsumeSuperBox(&view, /*recursion_limit=*/9);
ABSL_ASSERT_OK(superbox);
EXPECT_TRUE(view.empty()); // Entire buffer consumed.
EXPECT_EQ(superbox->description.type_uuid, kManifestStoreUuid);
ASSERT_EQ(superbox->contents.size(), 2);
// Active manifest from store2 should be placed LAST in contents.
const auto& box2 = superbox->contents.back();
EXPECT_TRUE(box2.Holds<SuperBox>());
EXPECT_EQ(box2.Get<SuperBox>().description.type_uuid, kStandardManifestUuid);
EXPECT_EQ(box2.Get<SuperBox>().description.label, "manifest_2");
// Initial manifest from store1 should be placed FIRST in contents.
const auto& box1 = superbox->contents.front();
EXPECT_TRUE(box1.Holds<SuperBox>());
EXPECT_EQ(box1.Get<SuperBox>().description.type_uuid, kStandardManifestUuid);
EXPECT_EQ(box1.Get<SuperBox>().description.label, "manifest_1");
}
TEST(ManifestStoreMergerTest, MalformedStoreReturnsError) {
std::string valid_store = CreateTestManifestStore("manifest_1", "data_1");
std::string malformed_store = "not a jumbf box";
EXPECT_FALSE(MergeManifestStores({valid_store, malformed_store}).ok());
}
} // namespace
} // namespace credentio