| // 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 "bindings/bmff_exclusion_checker.h" | |
| #include <string> | |
| #include "crypto/algorithms.h" | |
| #include "formats/bmff/hasher.h" | |
| #include "gtest/gtest.h" | |
| #include "proto/bmff_based_hash_assertion.pb.h" | |
| #include "testing/proto_test_utils.h" | |
| namespace credentio { | |
| namespace { | |
| using ::credentio_testing::ParseTextProtoOrDie; | |
| TEST(NoAdditionalExclusionsTest, NoExclusions) { | |
| BmffBasedHashAssertion assertion; | |
| EXPECT_FALSE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(NoAdditionalExclusionsTest, OnlyRequiredExclusions) { | |
| BmffBasedHashAssertion assertion = | |
| GetBmffHashTemplate(HashAlgorithm::kSha256); | |
| EXPECT_FALSE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(NoAdditionalExclusionsTest, WithSkipExclusion) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { xpath: "/skip" } | |
| )pb"); | |
| EXPECT_FALSE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, MerkleMapExclusionWithoutMerkleMaps) { | |
| BmffBasedHashAssertion assertion = | |
| GetBmffHashTemplate(HashAlgorithm::kSha256); | |
| auto exclusion = ParseTextProtoOrDie<BmffRange>(R"pb( | |
| xpath: "/mdat" | |
| subsets { offset: 16 length: 0 } | |
| )pb"); | |
| *assertion.add_exclusions() = exclusion; | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(NoAdditionalExclusionsTest, WithMerkleMaps) { | |
| BmffBasedHashAssertion assertion = | |
| GetBmffHashTemplate(HashAlgorithm::kSha256); | |
| auto exclusion = ParseTextProtoOrDie<BmffRange>(R"pb( | |
| xpath: "/mdat" | |
| subsets { offset: 16 length: 0 } | |
| )pb"); | |
| *assertion.add_exclusions() = exclusion; | |
| auto merkle = ParseTextProtoOrDie<BmffMerkle>(R"pb( | |
| unique_id: 1 | |
| local_id: 1 | |
| count: 1 | |
| alg: "sha256" | |
| init_hash: "\001\002\003" | |
| hashes: "\004\005\006" | |
| fixed_block_size: 1 | |
| )pb"); | |
| *assertion.add_merkles() = merkle; | |
| EXPECT_FALSE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(NoAdditionalExclusionsTest, ExclusionIsContainedWithinRequired) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { xpath: "/free[1]" } | |
| )pb"); | |
| EXPECT_FALSE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, ExclusionIsNotGuaranteedToBeContained) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { xpath: "/uuid/data" } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, WhenHasDifferentData) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { | |
| xpath: "/uuid" | |
| data { offset: 0 value: "\001\002\003" } | |
| } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, WhenHasDifferentSubsets) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { | |
| xpath: "/mdat" | |
| subsets { offset: 10 length: 4 } | |
| } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, RequiredExclusionWithSubsets) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { | |
| xpath: "/uuid" | |
| data { | |
| offset: 8 | |
| value: "\330\376\303\326\033\016H<\222\227X(\207~\304\201" | |
| } | |
| subsets { offset: 0 length: 128 } | |
| } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, FtypExclusionWithSubsets) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { | |
| xpath: "/ftyp" | |
| subsets { offset: 0 length: 8 } | |
| } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, MfraExclusionWithSubsets) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { | |
| xpath: "/mfra" | |
| subsets { offset: 0 length: 8 } | |
| } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, FtypExclusionWithPathExtension) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { xpath: "/ftyp/extra" } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| TEST(AdditionalExclusionsTest, MfraExclusionWithPathExtension) { | |
| auto assertion = ParseTextProtoOrDie<BmffBasedHashAssertion>(R"pb( | |
| exclusions { xpath: "/mfra/extra" } | |
| )pb"); | |
| EXPECT_TRUE(HasAdditionalExclusions(assertion)); | |
| } | |
| } // namespace | |
| } // namespace credentio |