| // 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/extractor.h" |
| |
| #include <string> |
| |
| #include "absl/status/status.h" |
| #include "absl/status/status_matchers.h" |
| #include "absl/strings/string_view.h" |
| #include "formats/byte_range.h" |
| #include "gmock/gmock.h" |
| #include "gtest/gtest.h" |
| #include "riegeli/bytes/string_reader.h" |
| |
| namespace credentio { |
| namespace { |
| |
| using ::absl_testing::StatusIs; |
| using ::testing::HasSubstr; |
| using ::testing::Optional; |
| |
| #ifndef ASSERT_OK_AND_ASSIGN |
| #define ASSERT_OK_AND_ASSIGN_CONCAT2(x, y) x##y |
| #define ASSERT_OK_AND_ASSIGN_CONCAT(x, y) ASSERT_OK_AND_ASSIGN_CONCAT2(x, y) |
| |
| #define ASSERT_OK_AND_ASSIGN(lhs, rexpr) \ |
| ASSERT_OK_AND_ASSIGN_IMPL(lhs, rexpr, __COUNTER__) |
| |
| #define ASSERT_OK_AND_ASSIGN_IMPL(lhs, rexpr, id) \ |
| auto ASSERT_OK_AND_ASSIGN_CONCAT(status_or_, id) = (rexpr); \ |
| ASSERT_THAT(ASSERT_OK_AND_ASSIGN_CONCAT(status_or_, id), \ |
| ::absl_testing::IsOk()); \ |
| lhs = std::move(*ASSERT_OK_AND_ASSIGN_CONCAT(status_or_, id)) |
| #endif |
| |
| constexpr absl::string_view kTestPdfContent = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNoC2paSubtype = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000155 00000 n \n" |
| "0000000238 00000 n \n" |
| "0000000298 00000 n \n" |
| "0000000338 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "397\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNoEmbeddedFilesRef = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(not_a_c2pa_manifest.txt) 1 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNamesNotDict = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names [1 0 R]>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 5\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "trailer\n" |
| "<</Root 4 0 R>>\n" |
| "startxref\n" |
| "328\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentEmbeddedFilesDirect = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names <</EmbeddedFiles <</Names " |
| "[(content_credential.c2pa) 3 0 R]>> >> >>\n" |
| "endobj\n" |
| "xref\n" |
| "0 5\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "trailer\n" |
| "<</Root 4 0 R>>\n" |
| "startxref\n" |
| "386\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNoAfRelationship = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentDifferentAfRelationship = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /Other /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNonIndirectAf = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [123 ] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentInvalidEmbeddedFilesType = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 12345>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNamesDictNotDict = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "12345 \n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNoEmbeddedFiles = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</OtherFiles___ 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 5 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| constexpr absl::string_view kTestPdfContentNamesObjectNotFound = |
| "%PDF-1.7\n" |
| "%%%%%\n" |
| "1 0 obj\n" |
| "<</Length 11>>\n" |
| "stream\n" |
| "test_stream\n" |
| "endstream\n" |
| "endobj\n" |
| "2 0 obj\n" |
| "<</Length 33 /Subtype /application#2fc2pa>>\n" |
| "stream\n" |
| "test_c2pa_manifest_raw_bytestream\n" |
| "endstream\n" |
| "endobj\n" |
| "3 0 obj\n" |
| "<</EF <</F 2 0 R>> /AFRelationship /C2PA_Manifest /Type /FileSpec>>\n" |
| "endobj\n" |
| "4 0 obj\n" |
| "<</Names [(content_credential.c2pa) 3 0 R]>>\n" |
| "endobj\n" |
| "5 0 obj\n" |
| "<</EmbeddedFiles 4 0 R>>\n" |
| "endobj\n" |
| "6 0 obj\n" |
| "<</AF [3 0 R] /Type /Catalog /Names 9 0 R>>\n" |
| "endobj\n" |
| "xref\n" |
| "0 7\n" |
| "0000000000 65535 f \n" |
| "0000000015 00000 n \n" |
| "0000000074 00000 n \n" |
| "0000000184 00000 n \n" |
| "0000000267 00000 n \n" |
| "0000000327 00000 n \n" |
| "0000000367 00000 n \n" |
| "trailer\n" |
| "<</Root 6 0 R>>\n" |
| "startxref\n" |
| "426\n" |
| "%%EOF"; |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreV22EmbeddedFilesDirect) { |
| riegeli::StringReader<> input(kTestPdfContentEmbeddedFilesDirect); |
| PdfExtractor extractor; |
| ASSERT_OK_AND_ASSIGN(auto manifest_store, |
| extractor.ExtractManifestStore(input)); |
| EXPECT_THAT(manifest_store, "test_c2pa_manifest_raw_bytestream"); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreV22) { |
| riegeli::StringReader<> input(kTestPdfContent); |
| PdfExtractor extractor; |
| ASSERT_OK_AND_ASSIGN(auto manifest_store, |
| extractor.ExtractManifestStore(input)); |
| EXPECT_THAT(manifest_store, "test_c2pa_manifest_raw_bytestream"); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreNoSubtype) { |
| riegeli::StringReader<> input(kTestPdfContentNoC2paSubtype); |
| PdfExtractor extractor; |
| ASSERT_OK_AND_ASSIGN(auto manifest_store, |
| extractor.ExtractManifestStore(input)); |
| EXPECT_THAT(manifest_store, "test_c2pa_manifest_raw_bytestream"); |
| } |
| |
| TEST(PdfExtractorTest, |
| ExtractManifestStoreThrowNotFoundErrorIfNoEmbeddedFilesRef) { |
| riegeli::StringReader<> input(kTestPdfContentNoEmbeddedFilesRef); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kNotFound)); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreLocation) { |
| riegeli::StringReader<> input(kTestPdfContent); |
| PdfExtractor extractor; |
| ASSERT_OK_AND_ASSIGN( |
| auto manifest_store_location, |
| extractor.ExtractManifestStoreLocation(input, {.requires_c2pa = true})); |
| EXPECT_THAT(manifest_store_location, |
| Optional(ByteRange{.offset = 74, .length = 109})); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreLocationNoSubtype) { |
| riegeli::StringReader<> input(kTestPdfContentNoC2paSubtype); |
| PdfExtractor extractor; |
| ASSERT_OK_AND_ASSIGN( |
| auto manifest_store_location, |
| extractor.ExtractManifestStoreLocation(input, {.requires_c2pa = true})); |
| EXPECT_THAT(manifest_store_location, |
| Optional(ByteRange{.offset = 74, .length = 80})); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreFailsWithInvalidNamesType) { |
| riegeli::StringReader<> input(kTestPdfContentNamesNotDict); |
| PdfExtractor extractor; |
| EXPECT_THAT( |
| extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| ::testing::AllOf(HasSubstr("Unexpected object type found."), |
| HasSubstr("credentio::Object::")))); |
| } |
| |
| TEST(PdfExtractorTest, ExtractBoxesUnimplemented) { |
| riegeli::StringReader<> input("test_content"); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractBoxes(input, {.requires_c2pa = true}), |
| StatusIs(absl::StatusCode::kUnimplemented)); |
| } |
| |
| TEST(PdfExtractorTest, |
| ExtractManifestStoreThrowsNotFoundErrorIfNoAfRelationship) { |
| riegeli::StringReader<> input(kTestPdfContentNoAfRelationship); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kNotFound, |
| HasSubstr("No manifest store found."))); |
| } |
| |
| TEST(PdfExtractorTest, |
| ExtractManifestStoreThrowsNotFoundErrorIfDifferentAfRelationship) { |
| riegeli::StringReader<> input(kTestPdfContentDifferentAfRelationship); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kNotFound, |
| HasSubstr("No manifest store found."))); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreThrowsNotFoundErrorIfNonIndirectAf) { |
| riegeli::StringReader<> input(kTestPdfContentNonIndirectAf); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kNotFound, |
| HasSubstr("No manifest store found."))); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreFailsWithInvalidEmbeddedFilesType) { |
| riegeli::StringReader<> input(kTestPdfContentInvalidEmbeddedFilesType); |
| PdfExtractor extractor; |
| EXPECT_THAT( |
| extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| ::testing::AllOf(HasSubstr("Unexpected object type found."), |
| HasSubstr("credentio::Object::")))); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreFailsIfNamesObjectNotDict) { |
| riegeli::StringReader<> input(kTestPdfContentNamesDictNotDict); |
| PdfExtractor extractor; |
| EXPECT_THAT( |
| extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kInvalidArgument, |
| HasSubstr("Object is not a credentio::Object::Dictionary"))); |
| } |
| |
| TEST(PdfExtractorTest, |
| ExtractManifestStoreThrowsNotFoundErrorIfNoEmbeddedFiles) { |
| riegeli::StringReader<> input(kTestPdfContentNoEmbeddedFiles); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kNotFound, |
| HasSubstr("No '/EmbeddedFiles' dictionary found."))); |
| } |
| |
| TEST(PdfExtractorTest, ExtractManifestStoreFailsIfNamesObjectNotFound) { |
| riegeli::StringReader<> input(kTestPdfContentNamesObjectNotFound); |
| PdfExtractor extractor; |
| EXPECT_THAT(extractor.ExtractManifestStore(input), |
| StatusIs(absl::StatusCode::kNotFound, |
| HasSubstr("No offset found for object number: 9"))); |
| } |
| |
| } // namespace |
| } // namespace credentio |