Files
pdf/engine/tests/qpdf_extractor_test.cpp
T
2026-06-16 19:06:48 +05:30

95 lines
3.0 KiB
C++

#include <gtest/gtest.h>
#include <pdfengine/content_stream.hpp>
#include "../src/qpdf/qpdf_extractor.hpp"
#include <filesystem>
#include <fstream>
using namespace pdfengine;
using namespace pdfengine::qpdf_layer;
#ifndef TEST_CORPUS_DIR
#define TEST_CORPUS_DIR "../../corpus"
#endif
namespace {
std::filesystem::path getCorpusPath(const std::string& subfolder, const std::string& filename) {
return std::filesystem::path(TEST_CORPUS_DIR) / subfolder / filename;
}
std::vector<uint8_t> readFile(const std::filesystem::path& path) {
std::ifstream file(path, std::ios::binary | std::ios::ate);
if (!file.is_open()) return {};
std::streamsize size = file.tellg();
file.seekg(0, std::ios::beg);
std::vector<uint8_t> buffer(size);
if (file.read(reinterpret_cast<char*>(buffer.data()), size)) {
return buffer;
}
return {};
}
}
class QpdfExtractorTest : public ::testing::Test {
protected:
QpdfExtractor extractor;
};
TEST_F(QpdfExtractorTest, ExtractFromMemory) {
auto path = getCorpusPath("basic", "hello_world.pdf");
auto stream = extractor.extractPageStream(path.string(), 0);
ASSERT_TRUE(stream.has_value());
EXPECT_EQ(stream->pageIndex, 0);
EXPECT_FALSE(stream->compressed); // Or true depending on qpdf, but we only verify success here
StreamVerification v = verifyContentStream(stream.value());
EXPECT_TRUE(v.hasBT);
EXPECT_TRUE(v.hasET);
EXPECT_TRUE(v.hasTf);
EXPECT_TRUE(v.hasTj);
}
TEST_F(QpdfExtractorTest, PageOutOfBounds) {
auto path = getCorpusPath("basic", "hello_world.pdf");
auto data = readFile(path);
ASSERT_FALSE(data.empty());
auto stream = extractor.extractPageStreamFromMemory(data, 1);
ASSERT_FALSE(stream.has_value());
EXPECT_EQ(stream.error(), QpdfError::PageOutOfBounds);
stream = extractor.extractPageStreamFromMemory(data, -1);
ASSERT_FALSE(stream.has_value());
EXPECT_EQ(stream.error(), QpdfError::PageOutOfBounds);
}
TEST_F(QpdfExtractorTest, CorruptPdf) {
std::vector<uint8_t> data = {0x00, 0x01, 0x02};
auto stream = extractor.extractPageStreamFromMemory(data, 0);
ASSERT_FALSE(stream.has_value());
EXPECT_EQ(stream.error(), QpdfError::InvalidFormat);
}
TEST_F(QpdfExtractorTest, EmptyContents) {
// about_blank.pdf usually has an empty page or no text
auto path = getCorpusPath("basic", "about_blank.pdf");
auto stream = extractor.extractPageStream(path.string(), 0);
ASSERT_TRUE(stream.has_value());
EXPECT_EQ(stream->pageIndex, 0);
StreamVerification v = verifyContentStream(stream.value());
EXPECT_FALSE(v.hasTj);
}
TEST_F(QpdfExtractorTest, VerifyNoText) {
// black.pdf or rectangles.pdf has no text, just graphics
auto path = getCorpusPath("basic", "black.pdf");
auto stream = extractor.extractPageStream(path.string(), 0);
ASSERT_TRUE(stream.has_value());
StreamVerification v = verifyContentStream(stream.value());
EXPECT_FALSE(v.hasBT);
EXPECT_FALSE(v.hasET);
EXPECT_FALSE(v.hasTf);
EXPECT_FALSE(v.hasTj);
}