89 lines
3.0 KiB
C++
89 lines
3.0 KiB
C++
#include <gtest/gtest.h>
|
|
#include "../src/qpdf/qpdf_extractor.hpp"
|
|
#include "../src/qpdf/qpdf_writer.hpp"
|
|
#include "../src/parser/lexer.hpp"
|
|
#include "../src/parser/parser.hpp"
|
|
#include "../src/parser/content_builder.hpp"
|
|
#include "../src/serializer/content_serializer.hpp"
|
|
#include "../src/serializer/ast_serializer.hpp"
|
|
#include <filesystem>
|
|
#include <fstream>
|
|
|
|
#ifndef TEST_CORPUS_DIR
|
|
#define TEST_CORPUS_DIR "../../corpus"
|
|
#endif
|
|
|
|
using namespace pdfengine;
|
|
using namespace pdfengine::qpdf_layer;
|
|
|
|
TEST(QpdfWriterTest, IntegrationReadModifyWrite) {
|
|
std::filesystem::path sourcePath = std::filesystem::path(TEST_CORPUS_DIR) / "basic" / "hello_world.pdf";
|
|
std::filesystem::path destPath = std::filesystem::path(TEST_CORPUS_DIR) / "basic" / "hello_world_modified.pdf";
|
|
|
|
// 1. Extract
|
|
QpdfExtractor extractor;
|
|
auto stream = extractor.extractPageStream(sourcePath.string(), 0);
|
|
ASSERT_TRUE(stream.has_value());
|
|
|
|
// 2. Lex, Parse, Build
|
|
Lexer lexer(stream->decodedContent);
|
|
auto tokens = lexer.tokenize();
|
|
ContentParser parser(tokens);
|
|
auto ops = parser.parse();
|
|
ContentBuilder builder;
|
|
auto objects = builder.build(ops);
|
|
|
|
// 3. Modify Text
|
|
bool foundAndModified = false;
|
|
for (auto& obj : objects) {
|
|
if (obj->getType() == ContentObjectType::Text) {
|
|
auto* textObj = static_cast<TextObject*>(obj.get());
|
|
if (textObj->text == "Hello, world!") {
|
|
textObj->text = "Hello, PDF Editor!";
|
|
foundAndModified = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
ASSERT_TRUE(foundAndModified) << "Could not find 'Hello, world!' to modify";
|
|
|
|
// 4. Serialize back to Ops
|
|
ContentSerializer contentSerializer;
|
|
auto newOps = contentSerializer.serialize(objects);
|
|
|
|
// 5. Serialize to raw bytes
|
|
AstSerializer astSerializer;
|
|
std::string newRawStream = astSerializer.serialize(newOps);
|
|
|
|
// 6. Write and Save PDF
|
|
QpdfWriter writer;
|
|
auto writeRes = writer.replacePageStreamAndSave(sourcePath.string(), destPath.string(), 0, newRawStream);
|
|
ASSERT_TRUE(writeRes.has_value()) << writeRes.error();
|
|
|
|
// 7. Re-open and verify modification
|
|
auto verifyStream = extractor.extractPageStream(destPath.string(), 0);
|
|
ASSERT_TRUE(verifyStream.has_value());
|
|
|
|
Lexer verifyLexer(verifyStream->decodedContent);
|
|
auto verifyTokens = verifyLexer.tokenize();
|
|
ContentParser verifyParser(verifyTokens);
|
|
ContentBuilder verifyBuilder;
|
|
auto verifyObjects = verifyBuilder.build(verifyParser.parse());
|
|
|
|
bool verifiedModification = false;
|
|
for (auto& obj : verifyObjects) {
|
|
if (obj->getType() == ContentObjectType::Text) {
|
|
auto* textObj = static_cast<TextObject*>(obj.get());
|
|
if (textObj->text == "Hello, PDF Editor!") {
|
|
verifiedModification = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
EXPECT_TRUE(verifiedModification) << "Modified string was not successfully saved and reloaded!";
|
|
|
|
// Cleanup
|
|
std::filesystem::remove(destPath);
|
|
}
|