diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 09:06:44 +0000 |
commit | ed5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch) | |
tree | 7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /sw/qa/unit | |
parent | Initial commit. (diff) | |
download | libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip |
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'sw/qa/unit')
-rw-r--r-- | sw/qa/unit/data/sw-dialogs-test.txt | 207 | ||||
-rw-r--r-- | sw/qa/unit/data/sw-dialogs-test_2.txt | 76 | ||||
-rw-r--r-- | sw/qa/unit/sw-dialogs-test.cxx | 103 | ||||
-rw-r--r-- | sw/qa/unit/sw-dialogs-test_2.cxx | 94 | ||||
-rw-r--r-- | sw/qa/unit/swmodeltestbase.cxx | 768 | ||||
-rw-r--r-- | sw/qa/unit/uibase.cxx | 44 |
6 files changed, 1292 insertions, 0 deletions
diff --git a/sw/qa/unit/data/sw-dialogs-test.txt b/sw/qa/unit/data/sw-dialogs-test.txt new file mode 100644 index 000000000..93fb6911b --- /dev/null +++ b/sw/qa/unit/data/sw-dialogs-test.txt @@ -0,0 +1,207 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# This file contains all dialogs that the unit tests in the module +# will work on if it is in script mode. It will read one-by-one, +# try to open it and create a screenshot that will be saved in +# workdir/screenshots using the pattern of the ui-file name. +# +# Syntax: +# - empty lines are allowed +# - lines starting with '#' are treated as comment +# - all other lines should contain a *.ui filename in the same +# notation as in the dialog constructors (see code) + +# +# The 'known' dialogs which have a hard-coded representation +# in registerKnownDialogsByID/createDialogByID +# + +# No known dialogs in writer for now + +# +# Dialogs without a hard-coded representation. These will +# be visualized using a fallback based on weld::Builder +# + +# currently deactivated, leads to problems and the test to not work +# This is typically a hint that these should be hard-coded in the +# test case since they need some document and model data to work +# +# modules/swriter/ui/templatedialog(nRegion).ui +# modules/swriter/ui/autoformattable.ui +# modules/swriter/ui/endnotepage.ui +# modules/swriter/ui/footnotesendnotestabpage.ui +# modules/swriter/ui/linenumbering.ui +# modules/swriter/ui/footnotepage.ui +# modules/swriter/ui/outlinenumberingpage.ui +# modules/swriter/ui/picturepage.ui <- problems under Linux +# +# Problems under ASan/UBSan, SwEnvPreview needs SwEnvDlg as parent: +# modules/swriter/ui/envaddresspage.ui +# modules/swriter/ui/envformatpage.ui +# modules/swriter/ui/envprinterpage.ui + +modules/swriter/ui/abstractdialog.ui +modules/swriter/ui/addentrydialog.ui +modules/swriter/ui/addressblockdialog.ui +modules/swriter/ui/alreadyexistsdialog.ui +modules/swriter/ui/asciifilterdialog.ui +modules/swriter/ui/asksearchdialog.ui +modules/swriter/ui/assignfieldsdialog.ui +modules/swriter/ui/assignstylesdialog.ui +modules/swriter/ui/attachnamedialog.ui +modules/swriter/ui/authenticationsettingsdialog.ui +modules/swriter/ui/autotext.ui +modules/swriter/ui/bibliographyentry.ui +modules/swriter/ui/bulletsandnumbering.ui +modules/swriter/ui/businessdatapage.ui +modules/swriter/ui/cannotsavelabeldialog.ui +modules/swriter/ui/captiondialog.ui +modules/swriter/ui/captionoptions.ui +modules/swriter/ui/cardmediumpage.ui +modules/swriter/ui/ccdialog.ui +modules/swriter/ui/characterproperties.ui +modules/swriter/ui/charurlpage.ui +modules/swriter/ui/columndialog.ui +modules/swriter/ui/columnpage.ui +modules/swriter/ui/columnwidth.ui +modules/swriter/ui/conditionpage.ui +modules/swriter/ui/converttexttable.ui +modules/swriter/ui/createaddresslist.ui +modules/swriter/ui/createauthorentry.ui +modules/swriter/ui/createautomarkdialog.ui +modules/swriter/ui/customizeaddrlistdialog.ui +modules/swriter/ui/datasourcesunavailabledialog.ui +modules/swriter/ui/dropcapspage.ui +modules/swriter/ui/dropdownfielddialog.ui +modules/swriter/ui/editcategories.ui +modules/swriter/ui/editfielddialog.ui +modules/swriter/ui/editsectiondialog.ui +modules/swriter/ui/envdialog.ui +modules/swriter/ui/exchangedatabases.ui +modules/swriter/ui/fielddialog.ui +modules/swriter/ui/findentrydialog.ui +modules/swriter/ui/flddbpage.ui +modules/swriter/ui/flddocinfopage.ui +modules/swriter/ui/flddocumentpage.ui +modules/swriter/ui/fldfuncpage.ui +modules/swriter/ui/fldrefpage.ui +modules/swriter/ui/fldvarpage.ui +modules/swriter/ui/floatingsync.ui +modules/swriter/ui/footendnotedialog.ui +modules/swriter/ui/footnoteareapage.ui +modules/swriter/ui/formatsectiondialog.ui +modules/swriter/ui/formattablepage.ui +modules/swriter/ui/frmaddpage.ui +modules/swriter/ui/frmtypepage.ui +modules/swriter/ui/frmurlpage.ui +modules/swriter/ui/indentpage.ui +modules/swriter/ui/indexentry.ui +modules/swriter/ui/infonotfounddialog.ui +modules/swriter/ui/inforeadonlydialog.ui +modules/swriter/ui/inputfielddialog.ui +modules/swriter/ui/insertautotextdialog.ui +modules/swriter/ui/insertbookmark.ui +modules/swriter/ui/insertbreak.ui +modules/swriter/ui/insertcaption.ui +modules/swriter/ui/insertdbcolumnsdialog.ui +modules/swriter/ui/insertfootnote.ui +modules/swriter/ui/insertscript.ui +modules/swriter/ui/insertsectiondialog.ui +modules/swriter/ui/inserttable.ui +modules/swriter/ui/labeldialog.ui +modules/swriter/ui/labelformatpage.ui +modules/swriter/ui/labeloptionspage.ui +modules/swriter/ui/mailconfigpage.ui +modules/swriter/ui/mailmerge.ui +modules/swriter/ui/mailmergedialog.ui +modules/swriter/ui/managechangessidebar.ui +modules/swriter/ui/mergeconnectdialog.ui +modules/swriter/ui/mergetabledialog.ui +modules/swriter/ui/mmaddressblockpage.ui +modules/swriter/ui/mmcreatingdialog.ui +modules/swriter/ui/mmlayoutpage.ui +modules/swriter/ui/mmmailbody.ui +modules/swriter/ui/mmoutputtypepage.ui +modules/swriter/ui/mmresultemaildialog.ui +modules/swriter/ui/mmresultprintdialog.ui +modules/swriter/ui/mmresultsavedialog.ui +modules/swriter/ui/mmsalutationpage.ui +modules/swriter/ui/mmselectpage.ui +modules/swriter/ui/mmsendmails.ui +modules/swriter/ui/newuserindexdialog.ui +modules/swriter/ui/notebookbar.ui +modules/swriter/ui/numberingnamedialog.ui +modules/swriter/ui/numparapage.ui +modules/swriter/ui/optcaptionpage.ui +modules/swriter/ui/optcomparison.ui +modules/swriter/ui/optcompatpage.ui +modules/swriter/ui/optfonttabpage.ui +modules/swriter/ui/optformataidspage.ui +modules/swriter/ui/optgeneralpage.ui +modules/swriter/ui/optredlinepage.ui +modules/swriter/ui/opttablepage.ui +modules/swriter/ui/opttestpage.ui +modules/swriter/ui/outlinenumbering.ui +modules/swriter/ui/outlinepositionpage.ui +modules/swriter/ui/paradialog.ui +modules/swriter/ui/previewzoomdialog.ui +modules/swriter/ui/printeroptions.ui +modules/swriter/ui/printmergedialog.ui +modules/swriter/ui/printmonitordialog.ui +modules/swriter/ui/printoptionspage.ui +modules/swriter/ui/privateuserpage.ui +modules/swriter/ui/querycontinuebegindialog.ui +modules/swriter/ui/querycontinueenddialog.ui +modules/swriter/ui/querydefaultcompatdialog.ui +modules/swriter/ui/querysavelabeldialog.ui +modules/swriter/ui/renameautotextdialog.ui +modules/swriter/ui/renameentrydialog.ui +modules/swriter/ui/renameobjectdialog.ui +modules/swriter/ui/rowheight.ui +modules/swriter/ui/saveashtmldialog.ui +modules/swriter/ui/savelabeldialog.ui +modules/swriter/ui/sectionpage.ui +modules/swriter/ui/selectaddressdialog.ui +modules/swriter/ui/selectautotextdialog.ui +modules/swriter/ui/selectblockdialog.ui +modules/swriter/ui/selectindexdialog.ui +modules/swriter/ui/selecttabledialog.ui +modules/swriter/ui/sidebarstylepresets.ui +modules/swriter/ui/sidebartheme.ui +modules/swriter/ui/sidebarwrap.ui +modules/swriter/ui/sortdialog.ui +modules/swriter/ui/splittable.ui +modules/swriter/ui/statisticsinfopage.ui +modules/swriter/ui/stringinput.ui +modules/swriter/ui/subjectdialog.ui +modules/swriter/ui/tablecolumnpage.ui +modules/swriter/ui/tablepreviewdialog.ui +modules/swriter/ui/tableproperties.ui +modules/swriter/ui/tabletextflowpage.ui +modules/swriter/ui/testmailsettings.ui +modules/swriter/ui/textgridpage.ui +modules/swriter/ui/titlepage.ui +modules/swriter/ui/tocdialog.ui +modules/swriter/ui/tocentriespage.ui +modules/swriter/ui/tocindexpage.ui +modules/swriter/ui/tocstylespage.ui +modules/swriter/ui/tokenwidget.ui +modules/swriter/ui/viewoptionspage.ui +modules/swriter/ui/warndatasourcedialog.ui +modules/swriter/ui/warnemaildialog.ui +modules/swriter/ui/wordcount.ui +modules/swriter/ui/wrapdialog.ui +modules/swriter/ui/wrappage.ui +modules/swriter/ui/indexentry.ui +modules/swriter/ui/bibliographyentry.ui +modules/swriter/ui/inforeadonlydialog.ui +modules/swriter/ui/inforeadonlydialog.ui +modules/swriter/ui/inforeadonlydialog.ui diff --git a/sw/qa/unit/data/sw-dialogs-test_2.txt b/sw/qa/unit/data/sw-dialogs-test_2.txt new file mode 100644 index 000000000..9ddde7617 --- /dev/null +++ b/sw/qa/unit/data/sw-dialogs-test_2.txt @@ -0,0 +1,76 @@ +# -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# + +# see sw-dialogs-test.txt + +modules/swriter/ui/optcaptionpage.ui +modules/swriter/ui/optcomparison.ui +modules/swriter/ui/optcompatpage.ui +modules/swriter/ui/optfonttabpage.ui +modules/swriter/ui/optformataidspage.ui +modules/swriter/ui/optgeneralpage.ui +modules/swriter/ui/optredlinepage.ui +modules/swriter/ui/opttablepage.ui +modules/swriter/ui/opttestpage.ui +modules/swriter/ui/outlinenumbering.ui +modules/swriter/ui/outlinepositionpage.ui +modules/swriter/ui/paradialog.ui +modules/swriter/ui/previewzoomdialog.ui +modules/swriter/ui/printeroptions.ui +modules/swriter/ui/printmergedialog.ui +modules/swriter/ui/printmonitordialog.ui +modules/swriter/ui/printoptionspage.ui +modules/swriter/ui/privateuserpage.ui +modules/swriter/ui/querycontinuebegindialog.ui +modules/swriter/ui/querycontinueenddialog.ui +modules/swriter/ui/querydefaultcompatdialog.ui +modules/swriter/ui/querysavelabeldialog.ui +modules/swriter/ui/renameautotextdialog.ui +modules/swriter/ui/renameentrydialog.ui +modules/swriter/ui/renameobjectdialog.ui +modules/swriter/ui/rowheight.ui +modules/swriter/ui/saveashtmldialog.ui +modules/swriter/ui/savelabeldialog.ui +modules/swriter/ui/sectionpage.ui +modules/swriter/ui/selectaddressdialog.ui +modules/swriter/ui/selectautotextdialog.ui +modules/swriter/ui/selectblockdialog.ui +modules/swriter/ui/selectindexdialog.ui +modules/swriter/ui/selecttabledialog.ui +modules/swriter/ui/sidebarstylepresets.ui +modules/swriter/ui/sidebartheme.ui +modules/swriter/ui/sidebarwrap.ui +modules/swriter/ui/sortdialog.ui +modules/swriter/ui/splittable.ui +modules/swriter/ui/statisticsinfopage.ui +modules/swriter/ui/stringinput.ui +modules/swriter/ui/subjectdialog.ui +modules/swriter/ui/tablecolumnpage.ui +modules/swriter/ui/tablepreviewdialog.ui +modules/swriter/ui/tableproperties.ui +modules/swriter/ui/tabletextflowpage.ui +modules/swriter/ui/testmailsettings.ui +modules/swriter/ui/textgridpage.ui +modules/swriter/ui/titlepage.ui +modules/swriter/ui/tocdialog.ui +modules/swriter/ui/tocentriespage.ui +modules/swriter/ui/tocindexpage.ui +modules/swriter/ui/tocstylespage.ui +modules/swriter/ui/tokenwidget.ui +modules/swriter/ui/viewoptionspage.ui +modules/swriter/ui/warndatasourcedialog.ui +modules/swriter/ui/warnemaildialog.ui +modules/swriter/ui/wordcount.ui +modules/swriter/ui/wrapdialog.ui +modules/swriter/ui/wrappage.ui +modules/swriter/ui/indexentry.ui +modules/swriter/ui/bibliographyentry.ui +modules/swriter/ui/inforeadonlydialog.ui +modules/swriter/ui/inforeadonlydialog.ui +modules/swriter/ui/inforeadonlydialog.ui diff --git a/sw/qa/unit/sw-dialogs-test.cxx b/sw/qa/unit/sw-dialogs-test.cxx new file mode 100644 index 000000000..48652ca1d --- /dev/null +++ b/sw/qa/unit/sw-dialogs-test.cxx @@ -0,0 +1,103 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include <test/screenshot_test.hxx> +#include <rtl/bootstrap.hxx> +#include <osl/module.hxx> +#include <tools/svlibrary.h> +#include <vcl/abstdlg.hxx> + +class SwAbstractDialogFactory; + +using namespace ::com::sun::star; + +extern "C" { using Fn = SwAbstractDialogFactory * (*)(); } + // sw/source/ui/dialog/swuiexp.cxx + +/// Test opening a dialog in sw +class SwDialogsTest : public ScreenshotTest +{ +private: + css::uno::Reference<css::lang::XComponent> component_; + osl::Module libSwui_; + + /// helper method to populate KnownDialogs, called in setUp(). Needs to be + /// written and has to add entries to KnownDialogs + virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override; + + /// dialog creation for known dialogs by ID. Has to be implemented for + /// each registered known dialog + virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override; + +public: + SwDialogsTest(); + + void setUp() override; + + void tearDown() override; + + // try to open a dialog + void openAnyDialog(); + + CPPUNIT_TEST_SUITE(SwDialogsTest); + CPPUNIT_TEST(openAnyDialog); + CPPUNIT_TEST_SUITE_END(); +}; + +SwDialogsTest::SwDialogsTest() +{ +} + +void SwDialogsTest::setUp() +{ + ScreenshotTest::setUp(); + // Make sure the sw library's global pSwResMgr is initialized: + component_ = loadFromDesktop( + "private:factory/swriter", "com.sun.star.text.TextDocument"); + // Make sure the swui library's global pSwResMgr is initialized + // (alternatively to dynamically loading the library, SwCreateDialogFactory + // could be declared in an include file and this CppunitTest link against + // the swui library): + OUString url("${LO_LIB_DIR}/" SVLIBRARY("swui")); + rtl::Bootstrap::expandMacros(url); //TODO: detect failure + CPPUNIT_ASSERT(libSwui_.load(url, SAL_LOADMODULE_GLOBAL)); + auto fn = reinterpret_cast<Fn>( + libSwui_.getFunctionSymbol("SwCreateDialogFactory")); + CPPUNIT_ASSERT(fn != nullptr); + (*fn)(); +} + +void SwDialogsTest::tearDown() +{ + component_->dispose(); + ScreenshotTest::tearDown(); +} + +void SwDialogsTest::registerKnownDialogsByID(mapType& /*rKnownDialogs*/) +{ + // fill map of known dialogs +} + +VclPtr<VclAbstractDialog> SwDialogsTest::createDialogByID(sal_uInt32 /*nID*/) +{ + return nullptr; +} + +void SwDialogsTest::openAnyDialog() +{ + /// process input file containing the UXMLDescriptions of the dialogs to dump + processDialogBatchFile(u"sw/qa/unit/data/sw-dialogs-test.txt"); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(SwDialogsTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/unit/sw-dialogs-test_2.cxx b/sw/qa/unit/sw-dialogs-test_2.cxx new file mode 100644 index 000000000..42e8d4b78 --- /dev/null +++ b/sw/qa/unit/sw-dialogs-test_2.cxx @@ -0,0 +1,94 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <sal/config.h> +#include <test/screenshot_test.hxx> +#include <rtl/bootstrap.hxx> +#include <osl/module.hxx> +#include <tools/svlibrary.h> +#include <vcl/abstdlg.hxx> + +#include <swdll.hxx> + +class SwAbstractDialogFactory; + +using namespace ::com::sun::star; + +extern "C" { using Fn = SwAbstractDialogFactory * (*)(); } + // sw/source/ui/dialog/swuiexp.cxx + +/// Test opening a dialog in sw +class SwDialogsTest2 : public ScreenshotTest +{ +private: + osl::Module libSwui_; + + /// helper method to populate KnownDialogs, called in setUp(). Needs to be + /// written and has to add entries to KnownDialogs + virtual void registerKnownDialogsByID(mapType& rKnownDialogs) override; + + /// dialog creation for known dialogs by ID. Has to be implemented for + /// each registered known dialog + virtual VclPtr<VclAbstractDialog> createDialogByID(sal_uInt32 nID) override; + +public: + SwDialogsTest2(); + + void setUp() override; + + // try to open a dialog + void openAnyDialog(); + + CPPUNIT_TEST_SUITE(SwDialogsTest2); + CPPUNIT_TEST(openAnyDialog); + CPPUNIT_TEST_SUITE_END(); +}; + +SwDialogsTest2::SwDialogsTest2() +{ +} + +void SwDialogsTest2::setUp() +{ + ScreenshotTest::setUp(); + SwGlobals::ensure(); + // Make sure the swui library's global pSwResMgr is initialized + // (alternatively to dynamically loading the library, SwCreateDialogFactory + // could be declared in an include file and this CppunitTest link against + // the swui library): + OUString url("${LO_LIB_DIR}/" SVLIBRARY("swui")); + rtl::Bootstrap::expandMacros(url); //TODO: detect failure + CPPUNIT_ASSERT(libSwui_.load(url, SAL_LOADMODULE_GLOBAL)); + auto fn = reinterpret_cast<Fn>( + libSwui_.getFunctionSymbol("SwCreateDialogFactory")); + CPPUNIT_ASSERT(fn != nullptr); + (*fn)(); +} + +void SwDialogsTest2::registerKnownDialogsByID(mapType& /*rKnownDialogs*/) +{ + // fill map of known dialogs +} + +VclPtr<VclAbstractDialog> SwDialogsTest2::createDialogByID(sal_uInt32 /*nID*/) +{ + return nullptr; +} + +void SwDialogsTest2::openAnyDialog() +{ + /// process input file containing the UXMLDescriptions of the dialogs to dump + processDialogBatchFile(u"sw/qa/unit/data/sw-dialogs-test_2.txt"); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(SwDialogsTest2); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/unit/swmodeltestbase.cxx b/sw/qa/unit/swmodeltestbase.cxx new file mode 100644 index 000000000..707d306ce --- /dev/null +++ b/sw/qa/unit/swmodeltestbase.cxx @@ -0,0 +1,768 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ + +#include <swmodeltestbase.hxx> + +#include <com/sun/star/container/XContentEnumerationAccess.hpp> +#include <com/sun/star/document/XFilter.hpp> +#include <com/sun/star/document/XImporter.hpp> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/packages/zip/ZipFileAccess.hpp> +#include <com/sun/star/text/XPageCursor.hpp> +#include <com/sun/star/text/XTextTable.hpp> +#include <com/sun/star/text/XTextViewCursorSupplier.hpp> + +#include <comphelper/processfactory.hxx> +#include <comphelper/propertyvalue.hxx> +#include <comphelper/sequence.hxx> +#include <officecfg/Office/Common.hxx> +#include <rtl/ustrbuf.hxx> +#include <sfx2/app.hxx> +#include <unotools/mediadescriptor.hxx> +#include <unotools/streamwrap.hxx> +#include <unotools/ucbstreamhelper.hxx> + +#include <IDocumentLayoutAccess.hxx> +#include <docsh.hxx> +#include <rootfrm.hxx> +#include <unotxdoc.hxx> +#include <viewsh.hxx> + +using namespace css; + +void SwModelTestBase::paste(std::u16string_view aFilename, + uno::Reference<text::XTextRange> const& xTextRange) +{ + uno::Reference<document::XFilter> xFilter( + m_xSFactory->createInstance("com.sun.star.comp.Writer.RtfFilter"), uno::UNO_QUERY_THROW); + uno::Reference<document::XImporter> xImporter(xFilter, uno::UNO_QUERY_THROW); + xImporter->setTargetDocument(mxComponent); + std::unique_ptr<SvStream> pStream = utl::UcbStreamHelper::CreateStream( + m_directories.getURLFromSrc(u"/sw/qa/extras/") + aFilename, StreamMode::STD_READ); + CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, pStream->GetError()); + uno::Reference<io::XStream> xStream(new utl::OStreamWrapper(std::move(pStream))); + uno::Sequence aDescriptor{ comphelper::makePropertyValue("InputStream", xStream), + comphelper::makePropertyValue("InsertMode", true), + comphelper::makePropertyValue("TextInsertModeRange", xTextRange) }; + CPPUNIT_ASSERT(xFilter->filter(aDescriptor)); +} + +SwModelTestBase::SwModelTestBase(const OUString& pTestDocumentPath, const char* pFilter) + : mpXmlBuffer(nullptr) + , mpTestDocumentPath(pTestDocumentPath) + , mpFilter(pFilter) + , mnStartTime(0) + , mbExported(false) + , mbFontNameWYSIWYG(officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::get()) +{ + maTempFile.EnableKillingFile(); +} + +void SwModelTestBase::setUp() +{ + test::BootstrapFixture::setUp(); + mxDesktop.set( + css::frame::Desktop::create(comphelper::getComponentContext(getMultiServiceFactory()))); + SfxApplication::GetOrCreate(); + std::shared_ptr<comphelper::ConfigurationChanges> xChanges( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::set(false, xChanges); + xChanges->commit(); +} + +void SwModelTestBase::tearDown() +{ + if (mxComponent.is()) + mxComponent->dispose(); + std::shared_ptr<comphelper::ConfigurationChanges> xChanges( + comphelper::ConfigurationChanges::create()); + officecfg::Office::Common::Font::View::ShowFontBoxWYSIWYG::set(mbFontNameWYSIWYG, xChanges); + xChanges->commit(); + test::BootstrapFixture::tearDown(); +} + +void SwModelTestBase::executeImportTest(const char* filename, const char* pPassword) +{ + // If the testcase is stored in some other format, it's pointless to test. + if (mustTestImportOf(filename)) + { + maTempFile.EnableKillingFile(false); + header(); + std::unique_ptr<Resetter> const pChanges(preTest(filename)); + load(mpTestDocumentPath, filename, pPassword); + verify(); + finish(); + maTempFile.EnableKillingFile(); + } +} + +void SwModelTestBase::executeLoadVerifyReloadVerify(const char* filename, const char* pPassword) +{ + maTempFile.EnableKillingFile(false); + header(); + std::unique_ptr<Resetter> const pChanges(preTest(filename)); + load(mpTestDocumentPath, filename, pPassword); + if (mustTestImportOf(filename)) + { + verify(); + } + postLoad(filename); + reload(mpFilter, filename, pPassword); + verify(); + finish(); + maTempFile.EnableKillingFile(); +} + +void SwModelTestBase::executeLoadReloadVerify(const char* filename, const char* pPassword) +{ + maTempFile.EnableKillingFile(false); + header(); + std::unique_ptr<Resetter> const pChanges(preTest(filename)); + load(mpTestDocumentPath, filename, pPassword); + postLoad(filename); + reload(mpFilter, filename, pPassword); + verify(); + finish(); + maTempFile.EnableKillingFile(); +} + +void SwModelTestBase::executeImportExport(const char* filename, const char* pPassword) +{ + maTempFile.EnableKillingFile(false); + header(); + std::unique_ptr<Resetter> const pChanges(preTest(filename)); + load(mpTestDocumentPath, filename, pPassword); + save(OUString::createFromAscii(mpFilter), maTempFile); + maTempFile.EnableKillingFile(false); + verify(); + finish(); + maTempFile.EnableKillingFile(); +} + +void SwModelTestBase::dumpLayout(const uno::Reference<lang::XComponent>& rComponent) +{ + // create the xml writer + mpXmlBuffer = xmlBufferCreate(); + xmlTextWriterPtr pXmlWriter = xmlNewTextWriterMemory(mpXmlBuffer, 0); + (void)xmlTextWriterStartDocument(pXmlWriter, nullptr, nullptr, nullptr); + + // create the dump + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(rComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout(); + pLayout->dumpAsXml(pXmlWriter); + + // delete xml writer + (void)xmlTextWriterEndDocument(pXmlWriter); + xmlFreeTextWriter(pXmlWriter); +} + +void SwModelTestBase::discardDumpedLayout() +{ + if (mpXmlBuffer) + { + xmlBufferFree(mpXmlBuffer); + mpXmlBuffer = nullptr; + } +} + +void SwModelTestBase::calcLayout() +{ + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc(); + pDoc->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout(); +} + +int SwModelTestBase::getLength() const { return getBodyText().getLength(); } + +OUString SwModelTestBase::getBodyText() const +{ + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xTextDocument->getText(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + OUStringBuffer aBuf; + while (xParaEnum->hasMoreElements()) + { + uno::Reference<container::XEnumerationAccess> xRangeEnumAccess(xParaEnum->nextElement(), + uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xRangeEnum = xRangeEnumAccess->createEnumeration(); + while (xRangeEnum->hasMoreElements()) + { + uno::Reference<text::XTextRange> xRange(xRangeEnum->nextElement(), uno::UNO_QUERY); + aBuf.append(xRange->getString()); + } + } + return aBuf.makeStringAndClear(); +} + +uno::Reference<container::XNameAccess> SwModelTestBase::getStyles(const OUString& aFamily) +{ + uno::Reference<style::XStyleFamiliesSupplier> xStyleFamiliesSupplier(mxComponent, + uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xStyleFamilies + = xStyleFamiliesSupplier->getStyleFamilies(); + uno::Reference<container::XNameAccess> xStyleFamily(xStyleFamilies->getByName(aFamily), + uno::UNO_QUERY); + return xStyleFamily; +} + +uno::Reference<style::XAutoStyleFamily> SwModelTestBase::getAutoStyles(const OUString& aFamily) +{ + uno::Reference<style::XAutoStylesSupplier> xAutoStylesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<style::XAutoStyles> xAutoStyles(xAutoStylesSupplier->getAutoStyles()); + uno::Reference<style::XAutoStyleFamily> xAutoStyleFamily(xAutoStyles->getByName(aFamily), + uno::UNO_QUERY); + return xAutoStyleFamily; +} + +xmlDocUniquePtr SwModelTestBase::parseLayoutDump() +{ + if (!mpXmlBuffer) + dumpLayout(mxComponent); + + auto pBuffer = reinterpret_cast<const char*>(xmlBufferContent(mpXmlBuffer)); + SAL_INFO("sw", "SwModelTestBase::parseLayoutDump: pBuffer is '" << pBuffer << "'"); + return xmlDocUniquePtr(xmlParseMemory(pBuffer, xmlBufferLength(mpXmlBuffer))); +} + +OUString SwModelTestBase::parseDump(const OString& aXPath, const OString& aAttribute) +{ + xmlDocUniquePtr pXmlDoc = parseLayoutDump(); + + xmlXPathContextPtr pXmlXpathCtx = xmlXPathNewContext(pXmlDoc.get()); + xmlXPathObjectPtr pXmlXpathObj + = xmlXPathEvalExpression(BAD_CAST(aXPath.getStr()), pXmlXpathCtx); + CPPUNIT_ASSERT_MESSAGE("xpath evaluation failed", pXmlXpathObj); + xmlChar* pXpathStrResult; + if (pXmlXpathObj->type == XPATH_NODESET) + { + xmlNodeSetPtr pXmlNodes = pXmlXpathObj->nodesetval; + CPPUNIT_ASSERT_EQUAL_MESSAGE("xpath should match exactly 1 node", 1, + xmlXPathNodeSetGetLength(pXmlNodes)); + xmlNodePtr pXmlNode = pXmlNodes->nodeTab[0]; + if (aAttribute.getLength()) + pXpathStrResult = xmlGetProp(pXmlNode, BAD_CAST(aAttribute.getStr())); + else + pXpathStrResult = xmlNodeGetContent(pXmlNode); + } + else + { + // the xpath expression evaluated to a value, not a node + CPPUNIT_ASSERT_EQUAL_MESSAGE("attr name should not be supplied when xpath evals to a value", + sal_Int32(0), aAttribute.getLength()); + pXpathStrResult = xmlXPathCastToString(pXmlXpathObj); + CPPUNIT_ASSERT_MESSAGE("xpath result cannot be cast to string", pXpathStrResult); + } + + OUString aRet(reinterpret_cast<char*>(pXpathStrResult), xmlStrlen(pXpathStrResult), + RTL_TEXTENCODING_UTF8); + xmlFree(pXpathStrResult); + xmlFree(pXmlXpathObj); + xmlFree(pXmlXpathCtx); + + return aRet; +} + +bool SwModelTestBase::hasProperty(const uno::Reference<uno::XInterface>& obj, + const OUString& name) const +{ + uno::Reference<beans::XPropertySet> properties(obj, uno::UNO_QUERY_THROW); + return properties->getPropertySetInfo()->hasPropertyByName(name); +} + +xml::AttributeData SwModelTestBase::getUserDefineAttribute(const uno::Any& obj, + const OUString& name, + const OUString& rValue) const +{ + uno::Reference<container::XNameContainer> attrsCnt( + getProperty<uno::Any>(obj, "UserDefinedAttributes"), uno::UNO_QUERY_THROW); + + xml::AttributeData aValue; + attrsCnt->getByName(name) >>= aValue; + if (!rValue.isEmpty()) + CPPUNIT_ASSERT_EQUAL_MESSAGE("attribute of cell does not contain expected value", rValue, + aValue.Value); + + return aValue; +} + +int SwModelTestBase::getParagraphs(uno::Reference<text::XText> const& xText) +{ + int nRet = 0; + if (!xText.is()) + return nRet; + + uno::Reference<container::XEnumerationAccess> xParaEnumAccess(xText->getText(), uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration(); + while (xParaEnum->hasMoreElements()) + { + xParaEnum->nextElement(); + nRet++; + } + return nRet; +} + +int SwModelTestBase::getParagraphs() +{ + uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY); + return getParagraphs(xTextDocument->getText()); +} + +uno::Reference<text::XTextContent> +SwModelTestBase::getParagraphOrTable(int number, uno::Reference<text::XText> const& xText) const +{ + assert(number != 0); // this thing is 1-based + uno::Reference<container::XEnumerationAccess> paraEnumAccess; + if (xText.is()) + paraEnumAccess.set(xText, uno::UNO_QUERY); + else + { + uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY); + paraEnumAccess.set(textDocument->getText(), uno::UNO_QUERY); + } + uno::Reference<container::XEnumeration> paraEnum = paraEnumAccess->createEnumeration(); + for (int i = 1; i < number; ++i) + paraEnum->nextElement(); + uno::Reference<text::XTextContent> const xElem(paraEnum->nextElement(), uno::UNO_QUERY_THROW); + return xElem; +} + +uno::Reference<text::XTextRange> SwModelTestBase::getParagraph(int number, + const OUString& content) const +{ + uno::Reference<text::XTextRange> const xParagraph(getParagraphOrTable(number), + uno::UNO_QUERY_THROW); + if (!content.isEmpty()) + CPPUNIT_ASSERT_EQUAL_MESSAGE("paragraph does not have expected content", content, + xParagraph->getString()); + return xParagraph; +} + +sal_Int16 SwModelTestBase::getNumberingTypeOfParagraph(int nPara) +{ + sal_Int16 nNumberingType = -1; + uno::Reference<text::XTextRange> xPara(getParagraph(nPara)); + uno::Reference<beans::XPropertySet> properties(xPara, uno::UNO_QUERY); + bool isNumber = false; + properties->getPropertyValue("NumberingIsNumber") >>= isNumber; + if (isNumber) + { + uno::Reference<container::XIndexAccess> xLevels( + properties->getPropertyValue("NumberingRules"), uno::UNO_QUERY); + sal_Int16 nNumberingLevel = -1; + properties->getPropertyValue("NumberingLevel") >>= nNumberingLevel; + if (nNumberingLevel >= 0 && nNumberingLevel < xLevels->getCount()) + { + uno::Sequence<beans::PropertyValue> aPropertyValue; + xLevels->getByIndex(nNumberingLevel) >>= aPropertyValue; + auto pProp = std::find_if( + std::cbegin(aPropertyValue), std::cend(aPropertyValue), + [](const beans::PropertyValue& rProp) { return rProp.Name == "NumberingType"; }); + if (pProp != std::cend(aPropertyValue)) + nNumberingType = pProp->Value.get<sal_Int16>(); + } + } + return nNumberingType; +} + +uno::Reference<text::XTextRange> +SwModelTestBase::getParagraphOfText(int number, uno::Reference<text::XText> const& xText, + const OUString& content) const +{ + uno::Reference<text::XTextRange> const xParagraph(getParagraphOrTable(number, xText), + uno::UNO_QUERY_THROW); + if (!content.isEmpty()) + CPPUNIT_ASSERT_EQUAL_MESSAGE("paragraph does not contain expected content", content, + xParagraph->getString()); + return xParagraph; +} + +uno::Reference<beans::XPropertySet> +SwModelTestBase::getParagraphAnchoredObject(int const index, + uno::Reference<text::XTextRange> const& xPara) const +{ + uno::Reference<container::XContentEnumerationAccess> xContentEnumAccess(xPara, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xContentEnum + = xContentEnumAccess->createContentEnumeration("com.sun.star.text.TextContent"); + for (int i = 1; i < index; ++i) + { + xContentEnum->nextElement(); + } + return uno::Reference<beans::XPropertySet>(xContentEnum->nextElement(), uno::UNO_QUERY); +} + +uno::Reference<text::XTextRange> +SwModelTestBase::getRun(uno::Reference<text::XTextRange> const& xParagraph, int number, + const OUString& content) const +{ + uno::Reference<container::XEnumerationAccess> xRunEnumAccess(xParagraph, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xRunEnum = xRunEnumAccess->createEnumeration(); + for (int i = 1; i < number; ++i) + xRunEnum->nextElement(); + uno::Reference<text::XTextRange> xRun(xRunEnum->nextElement(), uno::UNO_QUERY); + if (!content.isEmpty()) + CPPUNIT_ASSERT_EQUAL_MESSAGE("run does not contain expected content", content, + xRun->getString()); + return xRun; +} + +OUString SwModelTestBase::getFormula(uno::Reference<text::XTextRange> const& xRun) const +{ + uno::Reference<container::XContentEnumerationAccess> xContentEnumAccess(xRun, uno::UNO_QUERY); + uno::Reference<container::XEnumeration> xContentEnum + = xContentEnumAccess->createContentEnumeration(""); + uno::Reference<beans::XPropertySet> xFormula(xContentEnum->nextElement(), uno::UNO_QUERY); + return getProperty<OUString>( + getProperty<uno::Reference<beans::XPropertySet>>(xFormula, "Model"), "Formula"); +} + +uno::Reference<table::XCell> +SwModelTestBase::getCell(uno::Reference<uno::XInterface> const& xTableIfc, OUString const& rCell, + OUString const& rContent) +{ + uno::Reference<text::XTextTable> const xTable(xTableIfc, uno::UNO_QUERY_THROW); + uno::Reference<table::XCell> const xCell(xTable->getCellByName(rCell), uno::UNO_SET_THROW); + if (!rContent.isEmpty()) + { + uno::Reference<text::XText> const xCellText(xCell, uno::UNO_QUERY_THROW); + CPPUNIT_ASSERT_EQUAL_MESSAGE("cell does not contain expected content", rContent, + xCellText->getString()); + } + return xCell; +} + +uno::Reference<drawing::XShape> SwModelTestBase::getShape(int number) +{ + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + uno::Reference<drawing::XShape> xShape(xDrawPage->getByIndex(number - 1), uno::UNO_QUERY); + return xShape; +} + +uno::Reference<drawing::XShape> SwModelTestBase::getShapeByName(std::u16string_view aName) +{ + uno::Reference<drawing::XShape> xRet; + + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<drawing::XDrawPage> xDrawPage = xDrawPageSupplier->getDrawPage(); + for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i) + { + uno::Reference<container::XNamed> xShape(xDrawPage->getByIndex(i), uno::UNO_QUERY); + if (xShape->getName() == aName) + { + xRet.set(xShape, uno::UNO_QUERY); + break; + } + } + + return xRet; +} + +uno::Reference<drawing::XShape> SwModelTestBase::getTextFrameByName(const OUString& aName) +{ + uno::Reference<text::XTextFramesSupplier> xTextFramesSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XNameAccess> xNameAccess = xTextFramesSupplier->getTextFrames(); + uno::Reference<drawing::XShape> xShape(xNameAccess->getByName(aName), uno::UNO_QUERY); + return xShape; +} + +void SwModelTestBase::setTestInteractionHandler(const char* pPassword, + std::vector<beans::PropertyValue>& rFilterOptions) +{ + OUString sPassword = OUString::createFromAscii(pPassword); + rFilterOptions.emplace_back(); + xInteractionHandler + = rtl::Reference<TestInteractionHandler>(new TestInteractionHandler(sPassword)); + uno::Reference<task::XInteractionHandler2> const xInteraction(xInteractionHandler); + rFilterOptions[0].Name = "InteractionHandler"; + rFilterOptions[0].Value <<= xInteraction; +} + +void SwModelTestBase::header() {} + +void SwModelTestBase::loadURLWithComponent(OUString const& rURL, OUString const& rComponent, + const char* pName, const char* pPassword) +{ + if (mxComponent.is()) + mxComponent->dispose(); + + std::vector<beans::PropertyValue> aFilterOptions; + + if (pPassword) + { + setTestInteractionHandler(pPassword, aFilterOptions); + } + + if (!maImportFilterOptions.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "FilterOptions"; + aValue.Value <<= maImportFilterOptions; + aFilterOptions.push_back(aValue); + } + + if (!maImportFilterName.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "FilterName"; + aValue.Value <<= maImportFilterName; + aFilterOptions.push_back(aValue); + } + + // Output name early, so in the case of a hang, the name of the hanging input file is visible. + if (pName) + std::cout << pName << ":\n"; + mnStartTime = osl_getGlobalTimer(); + mxComponent + = loadFromDesktop(rURL, rComponent, comphelper::containerToSequence(aFilterOptions)); + + if (pPassword) + { + CPPUNIT_ASSERT_MESSAGE("Password set but not requested", + xInteractionHandler->wasPasswordRequested()); + } + + discardDumpedLayout(); + if (pName && mustCalcLayoutOf(pName)) + calcLayout(); +} + +void SwModelTestBase::loadURL(OUString const& rURL, const char* pName, const char* pPassword) +{ + loadURLWithComponent(rURL, "com.sun.star.text.TextDocument", pName, pPassword); +} + +void SwModelTestBase::reload(const char* pFilter, const char* filename, const char* pPassword) +{ + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + OUString aFilterName = OUString::createFromAscii(pFilter); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= aFilterName; + if (!maFilterOptions.isEmpty()) + aMediaDescriptor["FilterOptions"] <<= maFilterOptions; + if (pPassword) + { + if (strcmp(pFilter, "Office Open XML Text")) + { + aMediaDescriptor["Password"] <<= OUString::createFromAscii(pPassword); + } + else + { + OUString sPassword = OUString::createFromAscii(pPassword); + css::uno::Sequence<css::beans::NamedValue> aEncryptionData{ + { "CryptoType", css::uno::Any(OUString("Standard")) }, + { "OOXPassword", css::uno::Any(sPassword) } + }; + aMediaDescriptor[utl::MediaDescriptor::PROP_ENCRYPTIONDATA] <<= aEncryptionData; + } + } + xStorable->storeToURL(maTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + uno::Reference<lang::XComponent> xComponent(xStorable, uno::UNO_QUERY); + xComponent->dispose(); + mbExported = true; + + std::vector<beans::PropertyValue> aFilterOptions; + if (pPassword) + { + setTestInteractionHandler(pPassword, aFilterOptions); + } + + if (!maImportFilterOptions.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "FilterOptions"; + aValue.Value <<= maImportFilterOptions; + aFilterOptions.push_back(aValue); + } + + if (!maImportFilterName.isEmpty()) + { + beans::PropertyValue aValue; + aValue.Name = "FilterName"; + aValue.Value <<= maImportFilterName; + aFilterOptions.push_back(aValue); + } + + mxComponent = loadFromDesktop(maTempFile.GetURL(), "com.sun.star.text.TextDocument", + comphelper::containerToSequence(aFilterOptions)); + if (pPassword) + { + CPPUNIT_ASSERT_MESSAGE("Password set but not requested", + xInteractionHandler->wasPasswordRequested()); + } + if (mustValidate(filename) || aFilterName == "writer8" + || aFilterName == "OpenDocument Text Flat XML") + { + if (aFilterName == "Office Open XML Text") + { + // too many validation errors right now + validate(maTempFile.GetFileName(), test::OOXML); + } + else if (aFilterName == "writer8" || aFilterName == "OpenDocument Text Flat XML") + { + validate(maTempFile.GetFileName(), test::ODF); + } + else if (aFilterName == "MS Word 97") + { + validate(maTempFile.GetFileName(), test::MSBINARY); + } + else + { + OString aMessage + = OString::Concat("validation requested, but don't know how to validate ") + + filename + " (" + OUStringToOString(aFilterName, RTL_TEXTENCODING_UTF8) + ")"; + CPPUNIT_FAIL(aMessage.getStr()); + } + } + discardDumpedLayout(); + if (mustCalcLayoutOf(filename)) + calcLayout(); +} + +void SwModelTestBase::save(const OUString& aFilterName, utl::TempFile& rTempFile) +{ + rTempFile.EnableKillingFile(); + uno::Reference<frame::XStorable> xStorable(mxComponent, uno::UNO_QUERY); + utl::MediaDescriptor aMediaDescriptor; + aMediaDescriptor["FilterName"] <<= aFilterName; + if (!maFilterOptions.isEmpty()) + aMediaDescriptor["FilterOptions"] <<= maFilterOptions; + xStorable->storeToURL(rTempFile.GetURL(), aMediaDescriptor.getAsConstPropertyValueList()); + // TODO: for now, validate only ODF here + if (aFilterName == "writer8" || aFilterName == "OpenDocument Text Flat XML") + { + validate(rTempFile.GetFileName(), test::ODF); + } +} + +void SwModelTestBase::loadAndSave(const char* pName) +{ + load(mpTestDocumentPath, pName); + save(OUString::createFromAscii(mpFilter), maTempFile); + mbExported = true; +} + +void SwModelTestBase::loadAndReload(const char* pName) +{ + load(mpTestDocumentPath, pName); + reload(mpFilter, pName); +} + +void SwModelTestBase::finish() +{ + sal_uInt32 nEndTime = osl_getGlobalTimer(); + std::cout << (nEndTime - mnStartTime) << std::endl; + discardDumpedLayout(); +} + +int SwModelTestBase::getPages() const +{ + uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY); + uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier( + xModel->getCurrentController(), uno::UNO_QUERY); + uno::Reference<text::XPageCursor> xCursor(xTextViewCursorSupplier->getViewCursor(), + uno::UNO_QUERY); + xCursor->jumpToLastPage(); + return xCursor->getPage(); +} + +int SwModelTestBase::getShapes() const +{ + uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxComponent, uno::UNO_QUERY); + uno::Reference<container::XIndexAccess> xDraws = xDrawPageSupplier->getDrawPage(); + return xDraws->getCount(); +} + +xmlDocUniquePtr SwModelTestBase::parseExport(const OUString& rStreamName) +{ + if (!mbExported) + return nullptr; + + return parseExportInternal(maTempFile.GetURL(), rStreamName); +} + +xmlDocUniquePtr SwModelTestBase::parseExportedFile() +{ + auto stream(SvFileStream(maTempFile.GetURL(), StreamMode::READ | StreamMode::TEMPORARY)); + return parseXmlStream(&stream); +} + +std::unique_ptr<SvStream> SwModelTestBase::parseExportStream(const OUString& url, + const OUString& rStreamName) +{ + // Read the stream we're interested in. + uno::Reference<packages::zip::XZipFileAccess2> xNameAccess + = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), + url); + uno::Reference<io::XInputStream> xInputStream(xNameAccess->getByName(rStreamName), + uno::UNO_QUERY); + CPPUNIT_ASSERT(xInputStream.is()); + std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); + return pStream; +} + +xmlDocUniquePtr SwModelTestBase::parseExportInternal(const OUString& url, + const OUString& rStreamName) +{ + std::unique_ptr<SvStream> pStream(parseExportStream(url, rStreamName)); + + xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); + pXmlDoc->name = reinterpret_cast<char*>(xmlStrdup( + reinterpret_cast<xmlChar const*>(OUStringToOString(url, RTL_TEXTENCODING_UTF8).getStr()))); + return pXmlDoc; +} + +void SwModelTestBase::registerNamespaces(xmlXPathContextPtr& pXmlXpathCtx) +{ + // docx + XmlTestTools::registerOOXMLNamespaces(pXmlXpathCtx); + // odt + XmlTestTools::registerODFNamespaces(pXmlXpathCtx); + // reqif-xhtml + xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("reqif-xhtml"), + BAD_CAST("http://www.w3.org/1999/xhtml")); +} + +SwDoc* SwModelTestBase::createSwDoc(std::u16string_view rDataDirectory, const char* pName) +{ + if (rDataDirectory.empty() || !pName) + loadURL("private:factory/swriter", nullptr); + else + load(rDataDirectory, pName); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + return pTextDoc->GetDocShell()->GetDoc(); +} + +SwDoc* SwModelTestBase::createSwWebDoc(std::u16string_view rDataDirectory, const char* pName) +{ + if (rDataDirectory.empty() || !pName) + loadURL("private:factory/swriter/web", nullptr); + else + load_web(rDataDirectory, pName); + + SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get()); + CPPUNIT_ASSERT(pTextDoc); + return pTextDoc->GetDocShell()->GetDoc(); +} + +void SwModelTestBase::WrapReqifFromTempFile(SvMemoryStream& rStream) +{ + rStream.WriteCharPtr("<reqif-xhtml:html xmlns:reqif-xhtml=\"http://www.w3.org/1999/xhtml\">\n"); + SvFileStream aFileStream(maTempFile.GetURL(), StreamMode::READ); + rStream.WriteStream(aFileStream); + rStream.WriteCharPtr("</reqif-xhtml:html>\n"); + rStream.Seek(0); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/qa/unit/uibase.cxx b/sw/qa/unit/uibase.cxx new file mode 100644 index 000000000..519510977 --- /dev/null +++ b/sw/qa/unit/uibase.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + */ + +#include <cppunit/TestFixture.h> +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/plugin/TestPlugIn.h> + +#include <tools/urlobj.hxx> + +#include <dbmgr.hxx> + +namespace +{ +/// Test suite for unit tests covering uibase code. +class Test : public CppUnit::TestFixture +{ +public: + void testTdf98168(); + + CPPUNIT_TEST_SUITE(Test); + CPPUNIT_TEST(testTdf98168); + CPPUNIT_TEST_SUITE_END(); +}; + +void Test::testTdf98168() +{ + INetURLObject aURL(u"file:///tmp/test.xlsx"); + // This was sw::DBConnURIType::UNKNOWN, xlsx was not recognized. + CPPUNIT_ASSERT_EQUAL(sw::DBConnURIType::CALC, sw::GetDBunoType(aURL)); +} + +CPPUNIT_TEST_SUITE_REGISTRATION(Test); +} + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |