diff --git a/src/odr/internal/common/file.cpp b/src/odr/internal/common/file.cpp index 3752448fb..61fe1b75c 100644 --- a/src/odr/internal/common/file.cpp +++ b/src/odr/internal/common/file.cpp @@ -10,15 +10,14 @@ namespace odr::internal { -DiskFile::DiskFile(const char *path) : DiskFile{Path(path)} {} +DiskFile::DiskFile(const char *path) : DiskFile{AbsPath(path)} {} -DiskFile::DiskFile(const std::string &path) : DiskFile{Path(path)} {} +DiskFile::DiskFile(const std::string &path) : DiskFile{AbsPath(path)} {} -DiskFile::DiskFile(Path path) { - if (!std::filesystem::is_regular_file(path.path())) { +DiskFile::DiskFile(AbsPath path) : m_path{std::move(path)} { + if (!std::filesystem::is_regular_file(m_path.path())) { throw FileNotFound(); } - m_path = AbsPath(std::filesystem::absolute(path.path())); } FileLocation DiskFile::location() const noexcept { return FileLocation::disk; } diff --git a/src/odr/internal/common/file.hpp b/src/odr/internal/common/file.hpp index d72a89add..4ca14d776 100644 --- a/src/odr/internal/common/file.hpp +++ b/src/odr/internal/common/file.hpp @@ -17,7 +17,7 @@ class DiskFile : public abstract::File { public: explicit DiskFile(const char *path); explicit DiskFile(const std::string &path); - explicit DiskFile(Path path); + explicit DiskFile(AbsPath path); [[nodiscard]] FileLocation location() const noexcept final; [[nodiscard]] std::size_t size() const final; diff --git a/src/odr/internal/common/path.cpp b/src/odr/internal/common/path.cpp index 3b418551b..f3c6ce979 100644 --- a/src/odr/internal/common/path.cpp +++ b/src/odr/internal/common/path.cpp @@ -324,6 +324,10 @@ Path::Iterator Path::Iterator::operator++(int) { return old; } +AbsPath AbsPath::current_working_directory() { + return AbsPath(std::filesystem::current_path()); +} + AbsPath::AbsPath() noexcept : Path("/") {} AbsPath::AbsPath(const char *c_string) : Path(c_string) { diff --git a/src/odr/internal/common/path.hpp b/src/odr/internal/common/path.hpp index 5971cfc3f..236e9026d 100644 --- a/src/odr/internal/common/path.hpp +++ b/src/odr/internal/common/path.hpp @@ -109,6 +109,8 @@ class Path { class AbsPath final : public Path { public: + static AbsPath current_working_directory(); + AbsPath() noexcept; explicit AbsPath(const char *c_string); explicit AbsPath(const std::string &string); diff --git a/src/odr/internal/common/temporary_file.cpp b/src/odr/internal/common/temporary_file.cpp index 07a553a36..58445b7be 100644 --- a/src/odr/internal/common/temporary_file.cpp +++ b/src/odr/internal/common/temporary_file.cpp @@ -13,7 +13,8 @@ TemporaryDiskFile::TemporaryDiskFile(const char *path) : DiskFile{path} {} TemporaryDiskFile::TemporaryDiskFile(const std::string &path) : DiskFile{path} {} -TemporaryDiskFile::TemporaryDiskFile(const Path &path) : DiskFile{path} {} +TemporaryDiskFile::TemporaryDiskFile(AbsPath path) + : DiskFile{std::move(path)} {} TemporaryDiskFile::TemporaryDiskFile(const TemporaryDiskFile &) = default; @@ -31,7 +32,7 @@ TemporaryDiskFile::operator=(TemporaryDiskFile &&) noexcept = default; const TemporaryDiskFileFactory &TemporaryDiskFileFactory::system_default() { static TemporaryDiskFileFactory instance( - Path(std::filesystem::temp_directory_path()), + AbsPath(std::filesystem::temp_directory_path()), default_random_file_name_generator()); return instance; } @@ -42,7 +43,7 @@ TemporaryDiskFileFactory::default_random_file_name_generator() { } TemporaryDiskFileFactory::TemporaryDiskFileFactory( - Path directory, RandomFileNameGenerator random_file_name_generator) + AbsPath directory, RandomFileNameGenerator random_file_name_generator) : m_directory{std::move(directory)}, m_random_file_name_generator{std::move(random_file_name_generator)} {} @@ -53,7 +54,7 @@ TemporaryDiskFileFactory::copy(const abstract::File &file) const { TemporaryDiskFile TemporaryDiskFileFactory::copy(std::istream &in) const { std::fstream file; - Path file_path; + AbsPath file_path; while (true) { std::string file_name = m_random_file_name_generator(); diff --git a/src/odr/internal/common/temporary_file.hpp b/src/odr/internal/common/temporary_file.hpp index 57ee7f22c..5d4a3df01 100644 --- a/src/odr/internal/common/temporary_file.hpp +++ b/src/odr/internal/common/temporary_file.hpp @@ -11,7 +11,7 @@ class TemporaryDiskFile final : public DiskFile { public: explicit TemporaryDiskFile(const char *path); explicit TemporaryDiskFile(const std::string &path); - explicit TemporaryDiskFile(const Path &path); + explicit TemporaryDiskFile(AbsPath path); TemporaryDiskFile(const TemporaryDiskFile &); TemporaryDiskFile(TemporaryDiskFile &&) noexcept; ~TemporaryDiskFile() override; @@ -27,14 +27,14 @@ class TemporaryDiskFileFactory final { static RandomFileNameGenerator default_random_file_name_generator(); explicit TemporaryDiskFileFactory( - Path directory, RandomFileNameGenerator random_file_name_generator = - default_random_file_name_generator()); + AbsPath directory, RandomFileNameGenerator random_file_name_generator = + default_random_file_name_generator()); [[nodiscard]] TemporaryDiskFile copy(const abstract::File &file) const; [[nodiscard]] TemporaryDiskFile copy(std::istream &in) const; private: - Path m_directory; + AbsPath m_directory; RandomFileNameGenerator m_random_file_name_generator; }; diff --git a/src/odr/internal/html/document.cpp b/src/odr/internal/html/document.cpp index df2f52a45..ba893cd47 100644 --- a/src/odr/internal/html/document.cpp +++ b/src/odr/internal/html/document.cpp @@ -45,7 +45,7 @@ void front(const Document &document, const WritingState &state) { } auto odr_css_file = File( - Path(state.config().resource_path).join(RelPath("odr.css")).string()); + AbsPath(state.config().resource_path).join(RelPath("odr.css")).string()); odr::HtmlResource odr_css_resource = html::HtmlResource::create(HtmlResourceType::css, "text/css", "odr.css", "odr.css", odr_css_file, true, false, true); @@ -62,7 +62,7 @@ void front(const Document &document, const WritingState &state) { if (document.document_type() == DocumentType::spreadsheet) { auto odr_spreadsheet_css_file = - File(Path(state.config().resource_path) + File(AbsPath(state.config().resource_path) .join(RelPath("odr_spreadsheet.css")) .string()); odr::HtmlResource odr_spreadsheet_css_resource = html::HtmlResource::create( @@ -122,8 +122,8 @@ void back(const Document &document, const WritingState &state) { out.write_element_end("div"); } - auto odr_js_file = - File(Path(state.config().resource_path).join(RelPath("odr.js")).string()); + auto odr_js_file = File( + AbsPath(state.config().resource_path).join(RelPath("odr.js")).string()); odr::HtmlResource odr_js_resource = html::HtmlResource::create( HtmlResourceType::js, "text/javascript", "odr.js", "odr.js", odr_js_file, true, false, true); diff --git a/src/odr/internal/html/pdf2htmlex_wrapper.cpp b/src/odr/internal/html/pdf2htmlex_wrapper.cpp index b83f6c841..b40d0e8d9 100644 --- a/src/odr/internal/html/pdf2htmlex_wrapper.cpp +++ b/src/odr/internal/html/pdf2htmlex_wrapper.cpp @@ -5,7 +5,6 @@ #include #include -#include #include #include #include diff --git a/src/odr/internal/html/wvware_wrapper.cpp b/src/odr/internal/html/wvware_wrapper.cpp index 47ee3881d..a2f869a74 100644 --- a/src/odr/internal/html/wvware_wrapper.cpp +++ b/src/odr/internal/html/wvware_wrapper.cpp @@ -5,13 +5,16 @@ #include #include -#include +#include #include #include +#include #include +#include #include +#include #include #include #include @@ -39,10 +42,10 @@ namespace { /// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wv.h#L2776-L2814 /// to allow for more state variables. struct TranslationState : public expand_data { - explicit TranslationState(html::HtmlWriter _out, const HtmlConfig &_config, - std::string _cache_path) - : expand_data{}, out(std::move(_out)), config{&_config}, - cache_path{std::move(_cache_path)} {} + explicit TranslationState(html::HtmlWriter _out, HtmlResources &_resources, + const HtmlConfig &_config, std::string _cache_path) + : expand_data{}, out(std::move(_out)), resources(&_resources), + config{&_config}, cache_path{std::move(_cache_path)} {} char *charset = nullptr; PAP *ppap = nullptr; @@ -54,10 +57,26 @@ struct TranslationState : public expand_data { std::size_t figure_number = 0; html::HtmlWriter out; + HtmlResources *resources; const HtmlConfig *config; std::string cache_path; }; +std::string figure_name(wvParseStruct *ps) { + auto *data = static_cast(ps->userData); + + std::size_t number = data->figure_number++; + std::string name = "figure" + std::to_string(number); + + return name; +} + +std::string figure_cache_path(wvParseStruct *ps, const std::string &name) { + auto *data = static_cast(ps->userData); + + return data->cache_path + "/" + name; +} + /// Originally from `text.c` `wvConvertUnicodeToHtml` /// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/text.c#L1999-L2154 int convert_unicode_to_html(wvParseStruct *ps, std::uint16_t char16) { @@ -283,7 +302,7 @@ void output_from_unicode(wvParseStruct *ps, std::uint16_t eachchar, } // TODO iconv could be cached - { g_iconv_close(g_iconv_handle); } + g_iconv_close(g_iconv_handle); } /// Originally from `wvWare.c` `wvStrangeNoGraphicData` @@ -303,68 +322,89 @@ void strange_no_graphic_data(wvParseStruct *ps, int graphicstype) { /// Originally from `wvWare.c` `wvPrintGraphics` /// https://github.com/opendocument-app/wvWare/blob/c015326b001f1ad6dfb1f5e718461c16c56cca5f/wvWare.c#L1239-L1287 /// simplified to HTML output -void print_graphics(wvParseStruct *ps, int graphicstype, int width, int height, - const std::string &path) { +void print_graphics(wvParseStruct *ps, int /*graphicstype*/, int width, + int height, const std::string &name) { // upstream converts to PNG, we just use the original format as the browser // should support them auto *data = static_cast(ps->userData); auto &out = data->out; - // TODO export/embed image - - out.out() << R"()
)"; + std::string path = figure_cache_path(ps, name); + + File file(path); + odr::HtmlResource resource = + HtmlResource::create(HtmlResourceType::image, "image/jpg", name, name, + file, false, false, true); + HtmlResourceLocation resource_location = + data->config->resource_locator(resource, *data->config); + data->resources->emplace_back(std::move(resource), resource_location); + + out.write_element_begin( + "img", HtmlElementOptions() + .set_close_type(HtmlCloseType::trailing) + .set_attributes([&](const HtmlAttributeWriterCallback &clb) { + clb("alt", "Error: image not found or unsupported"); + if (resource_location.has_value()) { + clb("src", resource_location.value()); + } else { + clb("src", [&](std::ostream &o) { + translate_image_src(file, o, *data->config); + }); + } + }) + .set_style("width:" + std::to_string(width) + + "px;height:" + std::to_string(height) + "px")); + out.write_element_begin( + "br", HtmlElementOptions().set_close_type(HtmlCloseType::trailing)); } -void handle_bitmap(wvParseStruct * /*ps*/, const std::string &name, - BitmapBlip *bitmap) { +void dump_bitmap(wvParseStruct *ps, const std::string &name, + BitmapBlip *bitmap) { + std::string path = figure_cache_path(ps, name); + wvStream *pwv = bitmap->m_pvBits; - FILE *fd = nullptr; - std::size_t size = 0, i; + std::size_t size = wvStream_size(pwv); + wvStream_rewind(pwv); - fd = fopen(name.c_str(), "wb"); - if (fd == nullptr) { - throw std::runtime_error("Cannot open " + name + " file for writing"); + std::ofstream bitmap_out(path, std::ios::binary); + if (bitmap_out.fail()) { + throw std::runtime_error("Cannot open " + path + " file for writing"); } - size = wvStream_size(pwv); - wvStream_rewind(pwv); - for (i = 0; i < size; i++) { - fputc(read_8ubit(pwv), fd); + for (std::size_t i = 0; i < size; i++) { + std::uint8_t byte = read_8ubit(pwv); + bitmap_out.put(static_cast(byte)); } - fclose(fd); } -int handle_metafile(wvParseStruct * /*ps*/, const std::string &name, - MetaFileBlip *bitmap) { - wvStream *pwv = bitmap->m_pvBits; - FILE *fd = nullptr; - std::size_t size = 0, i; - std::uint8_t decompressf = 0; +int dump_metafile(wvParseStruct *ps, const std::string &name, + MetaFileBlip *bitmap) { + std::string path = figure_cache_path(ps, name); - fd = fopen(name.c_str(), "wb"); + FILE *fd = fopen(path.c_str(), "wb"); if (fd == nullptr) { - throw std::runtime_error("Cannot open " + name + " file for writing"); + throw std::runtime_error("Cannot open " + path + " file for writing"); } - size = wvStream_size(pwv); + + wvStream *pwv = bitmap->m_pvBits; + std::size_t size = wvStream_size(pwv); wvStream_rewind(pwv); + std::uint8_t decompressf = 0; if (bitmap->m_fCompression == msocompressionDeflate) { decompressf = setdecom(); } - if (!decompressf) { - for (i = 0; i < size; i++) { + if (decompressf == 0) { + for (std::size_t i = 0; i < size; i++) { fputc(read_8ubit(pwv), fd); } - } else /* decompress here */ - { + } else { FILE *tmp = tmpfile(); FILE *out = tmpfile(); - for (i = 0; i < size; i++) { + for (std::size_t i = 0; i < size; i++) { fputc(read_8ubit(pwv), tmp); } @@ -374,7 +414,7 @@ int handle_metafile(wvParseStruct * /*ps*/, const std::string &name, rewind(out); - for (i = 0; i < bitmap->m_cb; i++) { + for (std::size_t i = 0; i < bitmap->m_cb; i++) { fputc(fgetc(out), fd); } @@ -385,27 +425,8 @@ int handle_metafile(wvParseStruct * /*ps*/, const std::string &name, return 0; } -std::string figure_name(wvParseStruct *ps) { - auto *data = static_cast(ps->userData); - - std::size_t number = data->figure_number++; - std::string name = "figure" + std::to_string(number); - - return name; -} - -std::string figure_path(wvParseStruct *ps) { - auto *data = static_cast(ps->userData); - - return data->cache_path + "/" + figure_name(ps); -} - std::string html_graphic(wvParseStruct *ps, Blip *blip) { - std::string path; - wvStream *fd; - char test[3]; - - path = figure_path(ps); + std::string name = figure_name(ps); /* temp hack to test older included bmps in word 6 and 7, @@ -415,49 +436,51 @@ std::string html_graphic(wvParseStruct *ps, Blip *blip) { switch (blip->type) { case msoblipJPEG: case msoblipDIB: - case msoblipPNG: - fd = (blip->blip.bitmap.m_pvBits); + case msoblipPNG: { + wvStream *fd = (blip->blip.bitmap.m_pvBits); + char test[3]; + test[0] = static_cast(read_8ubit(fd)); + test[1] = static_cast(read_8ubit(fd)); test[2] = '\0'; - test[0] = (char)read_8ubit(fd); - - test[1] = (char)read_8ubit(fd); wvStream_rewind(fd); - if (!(strcmp(test, "BM"))) { - path += ".bmp"; - handle_bitmap(ps, path, &blip->blip.bitmap); - return path; + if (strcmp(test, "BM") == 0) { + name += ".bmp"; + dump_bitmap(ps, name, &blip->blip.bitmap); + return name; } + } default: break; } switch (blip->type) { case msoblipWMF: - path += ".wmf"; - handle_metafile(ps, path, &blip->blip.metafile); + name += ".wmf"; + dump_metafile(ps, name, &blip->blip.metafile); break; case msoblipEMF: - path += ".emf"; - handle_metafile(ps, path, &blip->blip.metafile); + name += ".emf"; + dump_metafile(ps, name, &blip->blip.metafile); break; case msoblipPICT: - path += ".pict"; - handle_metafile(ps, path, &blip->blip.metafile); + name += ".pict"; + dump_metafile(ps, name, &blip->blip.metafile); break; case msoblipJPEG: - path += ".jpg"; - handle_bitmap(ps, path, &blip->blip.bitmap); + name += ".jpg"; + dump_bitmap(ps, name, &blip->blip.bitmap); break; case msoblipDIB: - path += ".dib"; - handle_bitmap(ps, path, &blip->blip.bitmap); + name += ".dib"; + dump_bitmap(ps, name, &blip->blip.bitmap); break; case msoblipPNG: - path += ".png"; - handle_bitmap(ps, path, &blip->blip.bitmap); + name += ".png"; + dump_bitmap(ps, name, &blip->blip.bitmap); break; } - return path; + + return name; } /// Originally from `wvWare.c` `myelehandler` @@ -697,9 +720,9 @@ int special_char_handler(wvParseStruct *ps, std::uint16_t eachchar, CHP *achp) { wvGetPICF(wvQuerySupported(&ps->fib, nullptr), &picf, ps->data); f = picf.rgb; if (wv0x01(&blip, f, picf.lcb - picf.cbHeader) != 0) { - std::string path = html_graphic(ps, &blip); + std::string name = html_graphic(ps, &blip); print_graphics(ps, 0x01, (int)wvTwipsToHPixels(picf.dxaGoal), - (int)wvTwipsToVPixels(picf.dyaGoal), path); + (int)wvTwipsToVPixels(picf.dyaGoal), name); } else { strange_no_graphic_data(ps, 0x01); } @@ -721,12 +744,12 @@ int special_char_handler(wvParseStruct *ps, std::uint16_t eachchar, CHP *achp) { data->props = fspa; if (wv0x08(&blip, (int)fspa->spid, ps) != 0) { - std::string path = html_graphic(ps, &blip); + std::string name = html_graphic(ps, &blip); print_graphics( ps, 0x08, (int)wvTwipsToHPixels((short)(fspa->xaRight - fspa->xaLeft)), (int)wvTwipsToVPixels((short)(fspa->yaBottom - fspa->yaTop)), - path); + name); } else { strange_no_graphic_data(ps, 0x08); } @@ -795,7 +818,7 @@ option to support correct symbol font conversion to a viewable format.\n"; return 0; } -class HtmlServiceImpl : public HtmlService { +class HtmlServiceImpl final : public HtmlService { public: HtmlServiceImpl(WvWareLegacyMicrosoftFile oldms_file, HtmlConfig config, std::string cache_path, std::shared_ptr logger) @@ -806,31 +829,75 @@ class HtmlServiceImpl : public HtmlService { std::make_shared(*this, "document", "document.html")); } - void warmup() const final {} - [[nodiscard]] const HtmlViews &list_views() const final { return m_views; } - [[nodiscard]] bool exists(const std::string &path) const final { - if (path == "document.html") { + void warmup() const final { + std::lock_guard lock(m_mutex); + + if (m_warm) { + return; + } + + std::ofstream document_out(m_cache_path + "/document.html"); + HtmlWriter out(document_out, config()); + m_resources = write_document(out); + + m_warm = true; + } + + bool exists(const std::string &path) const final { + if (std::ranges::any_of(m_views, [&path](const auto &view) { + return view.path() == path; + })) { + return true; + } + + warmup(); + + if (std::ranges::any_of(m_resources, [&path](const auto &pair) { + const auto &[resource, location] = pair; + return location.has_value() && location.value() == path; + })) { return true; } return false; } - [[nodiscard]] std::string mimetype(const std::string &path) const final { - if (path == "document.html") { + std::string mimetype(const std::string &path) const final { + if (std::ranges::any_of(m_views, [&path](const auto &view) { + return view.path() == path; + })) { return "text/html"; } + warmup(); + + for (const auto &[resource, location] : m_resources) { + if (location.has_value() && location.value() == path) { + return resource.mime_type(); + } + } + throw FileNotFound("Unknown path: " + path); } void write(const std::string &path, std::ostream &out) const final { - if (path == "document.html") { - HtmlWriter writer(out, config()); - write_document(writer); - return; + for (const auto &view : m_views) { + if (view.path() == path) { + HtmlWriter writer(out, config()); + write_html(path, writer); + return; + } + } + + warmup(); + + for (const auto &[resource, location] : m_resources) { + if (location.has_value() && location.value() == path) { + resource.write_resource(out); + return; + } } throw FileNotFound("Unknown path: " + path); @@ -838,11 +905,11 @@ class HtmlServiceImpl : public HtmlService { HtmlResources write_html(const std::string &path, html::HtmlWriter &out) const final { - if (path == "document.html") { - return write_document(out); - } + warmup(); - throw FileNotFound("Unknown path: " + path); + util::file::pipe(m_cache_path + "/" + path, out.out()); + + return m_resources; } HtmlResources write_document(HtmlWriter &out) const { @@ -856,7 +923,7 @@ class HtmlServiceImpl : public HtmlService { wvSetSpecialCharHandler(&ps, special_char_handler); state_data handle; - TranslationState translation_state(out, config(), m_cache_path); + TranslationState translation_state(out, resources, config(), m_cache_path); wvInitStateData(&handle); @@ -886,9 +953,13 @@ class HtmlServiceImpl : public HtmlService { protected: WvWareLegacyMicrosoftFile m_oldms_file; + std::string m_cache_path; + HtmlViews m_views; - std::string m_cache_path; + mutable std::mutex m_mutex; + mutable bool m_warm = false; + mutable HtmlResources m_resources; }; } // namespace diff --git a/test/data/reference-output/odr-public b/test/data/reference-output/odr-public index 5e231df83..58cce125c 160000 --- a/test/data/reference-output/odr-public +++ b/test/data/reference-output/odr-public @@ -1 +1 @@ -Subproject commit 5e231df837b7ee94bf499f30210fcb6d20b960f2 +Subproject commit 58cce125cfbad85f90328c8e0ec6310e8bae2d58 diff --git a/test/scripts/compare_output_server.sh b/test/scripts/compare_output_server.sh index ec1a25e48..9bd626780 100755 --- a/test/scripts/compare_output_server.sh +++ b/test/scripts/compare_output_server.sh @@ -17,5 +17,5 @@ docker run -ti \ -v $(pwd):/repo \ -p 8000:8000 \ --platform linux/amd64 \ - ghcr.io/opendocument-app/odr_core_test \ + ghcr.io/opendocument-app/odr_core_test:1.0.14 \ compare-html-server /repo/$REF /repo/$OBS --compare --driver $DRIVER --port 8000 diff --git a/test/src/document_test.cpp b/test/src/document_test.cpp index 753531505..c7dd1f6f5 100644 --- a/test/src/document_test.cpp +++ b/test/src/document_test.cpp @@ -1,12 +1,13 @@ #include #include #include -#include #include #include +#include + using namespace odr; using namespace odr::test; @@ -71,8 +72,10 @@ TEST(Document, edit_odt) { }; edit(document.root_element()); - document.save("about_edit.odt"); - DocumentFile("about_edit.odt"); + std::string output_path = + (std::filesystem::current_path() / "about_edit.odt").string(); + document.save(output_path); + DocumentFile{output_path}; } TEST(Document, edit_docx) { @@ -93,8 +96,10 @@ TEST(Document, edit_docx) { }; edit(document.root_element()); - document.save("style-various-1_edit.docx"); - DocumentFile("style-various-1_edit.docx"); + std::string output_path = + (std::filesystem::current_path() / "style-various-1_edit.docx").string(); + document.save(output_path); + DocumentFile{output_path}; } TEST(Document, edit_odt_diff) { @@ -108,8 +113,11 @@ TEST(Document, edit_odt_diff) { html::edit(document, diff); - document.save("style-various-1_edit_diff.odt"); - DocumentFile("style-various-1_edit_diff.odt"); + std::string output_path = + (std::filesystem::current_path() / "style-various-1_edit_diff.odt") + .string(); + document.save(output_path); + DocumentFile{output_path}; } TEST(Document, edit_ods_diff) { @@ -125,8 +133,10 @@ TEST(Document, edit_ods_diff) { html::edit(document, diff); - document.save("pages_edit_diff.ods"); - DocumentFile("pages_edit_diff.ods"); + std::string output_path = + (std::filesystem::current_path() / "pages_edit_diff.ods").string(); + document.save(output_path); + DocumentFile{output_path}; } TEST(Document, edit_docx_diff) { @@ -141,6 +151,9 @@ TEST(Document, edit_docx_diff) { html::edit(document, diff); - document.save("style-various-1_edit_diff.docx"); - DocumentFile("style-various-1_edit_diff.docx"); + std::string output_path = + (std::filesystem::current_path() / "style-various-1_edit_diff.docx") + .string(); + document.save(output_path); + DocumentFile{output_path}; } diff --git a/test/src/html_output_test.cpp b/test/src/html_output_test.cpp index 2f3641631..6d30e1e94 100644 --- a/test/src/html_output_test.cpp +++ b/test/src/html_output_test.cpp @@ -211,12 +211,15 @@ TestParams create_test_params(const TestFile &test_file, const DecoderEngine engine) { const std::string test_file_path = test_file.short_path; - const std::string test_repo = *Path(test_file_path).begin(); - const std::string output_path_prefix = - Path("output").join(RelPath(test_repo)).join(RelPath("output")).string(); + const std::string test_repo = *RelPath(test_file_path).begin(); + const std::string output_path_prefix = AbsPath::current_working_directory() + .join(RelPath("output")) + .join(RelPath(test_repo)) + .join(RelPath("output")) + .string(); const std::string output_path_suffix = engine_suffix(engine); const std::string output_path = - Path(output_path_prefix) + AbsPath(output_path_prefix) .join(RelPath(test_file_path).rebase(RelPath(test_repo))) .string() + output_path_suffix; diff --git a/test/src/internal/zip/zip_archive_test.cpp b/test/src/internal/zip/zip_archive_test.cpp index 88a1575c3..838e30fee 100644 --- a/test/src/internal/zip/zip_archive_test.cpp +++ b/test/src/internal/zip/zip_archive_test.cpp @@ -9,6 +9,7 @@ #include +#include #include #include @@ -53,7 +54,8 @@ TEST(ZipArchive, create_and_save) { } TEST(ZipArchive, create) { - const std::string path = "created.zip"; + const std::string path = + (std::filesystem::current_path() / "created.zip").string(); { ZipArchive zip; @@ -97,7 +99,8 @@ TEST(ZipArchive, create) { } TEST(ZipArchive, create_order) { - const std::string path = "created.zip"; + const std::string path = + (std::filesystem::current_path() / "created.zip").string(); const std::vector entries{"z", "one", "two", "three", "a", "0"}; {