/* -*- 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace css; void SwModelTestBase::paste(std::u16string_view aFilename, uno::Reference const& xTextRange) { uno::Reference xFilter( m_xSFactory->createInstance("com.sun.star.comp.Writer.RtfFilter"), uno::UNO_QUERY_THROW); uno::Reference xImporter(xFilter, uno::UNO_QUERY_THROW); xImporter->setTargetDocument(mxComponent); std::unique_ptr pStream = utl::UcbStreamHelper::CreateStream( m_directories.getURLFromSrc(u"/sw/qa/extras/") + aFilename, StreamMode::STD_READ); CPPUNIT_ASSERT_EQUAL(ERRCODE_NONE, pStream->GetError()); uno::Reference 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 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 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 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 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 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 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& 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(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() { getSwDoc()->getIDocumentLayoutAccess().GetCurrentViewShell()->CalcLayout(); } int SwModelTestBase::getLength() const { return getBodyText().getLength(); } OUString SwModelTestBase::getBodyText() const { uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); uno::Reference xParaEnumAccess(xTextDocument->getText(), uno::UNO_QUERY); uno::Reference xParaEnum = xParaEnumAccess->createEnumeration(); OUStringBuffer aBuf; while (xParaEnum->hasMoreElements()) { uno::Reference xRangeEnumAccess(xParaEnum->nextElement(), uno::UNO_QUERY); uno::Reference xRangeEnum = xRangeEnumAccess->createEnumeration(); while (xRangeEnum->hasMoreElements()) { uno::Reference xRange(xRangeEnum->nextElement(), uno::UNO_QUERY); aBuf.append(xRange->getString()); } } return aBuf.makeStringAndClear(); } uno::Reference SwModelTestBase::getStyles(const OUString& aFamily) { uno::Reference xStyleFamiliesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xStyleFamilies = xStyleFamiliesSupplier->getStyleFamilies(); uno::Reference xStyleFamily(xStyleFamilies->getByName(aFamily), uno::UNO_QUERY); return xStyleFamily; } uno::Reference SwModelTestBase::getAutoStyles(const OUString& aFamily) { uno::Reference xAutoStylesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xAutoStyles(xAutoStylesSupplier->getAutoStyles()); uno::Reference xAutoStyleFamily(xAutoStyles->getByName(aFamily), uno::UNO_QUERY); return xAutoStyleFamily; } xmlDocUniquePtr SwModelTestBase::parseLayoutDump() { if (!mpXmlBuffer) dumpLayout(mxComponent); auto pBuffer = reinterpret_cast(xmlBufferContent(mpXmlBuffer)); SAL_INFO("sw.qa", "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(pXpathStrResult), xmlStrlen(pXpathStrResult), RTL_TEXTENCODING_UTF8); xmlFree(pXpathStrResult); xmlFree(pXmlXpathObj); xmlFree(pXmlXpathCtx); return aRet; } bool SwModelTestBase::hasProperty(const uno::Reference& obj, const OUString& name) const { uno::Reference 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 attrsCnt( getProperty(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 const& xText) { int nRet = 0; if (!xText.is()) return nRet; uno::Reference xParaEnumAccess(xText->getText(), uno::UNO_QUERY); uno::Reference xParaEnum = xParaEnumAccess->createEnumeration(); while (xParaEnum->hasMoreElements()) { xParaEnum->nextElement(); nRet++; } return nRet; } int SwModelTestBase::getParagraphs() { uno::Reference xTextDocument(mxComponent, uno::UNO_QUERY); return getParagraphs(xTextDocument->getText()); } uno::Reference SwModelTestBase::getParagraphOrTable(int number, uno::Reference const& xText) const { assert(number != 0); // this thing is 1-based uno::Reference paraEnumAccess; if (xText.is()) paraEnumAccess.set(xText, uno::UNO_QUERY); else { uno::Reference textDocument(mxComponent, uno::UNO_QUERY); paraEnumAccess.set(textDocument->getText(), uno::UNO_QUERY); } uno::Reference paraEnum = paraEnumAccess->createEnumeration(); for (int i = 1; i < number; ++i) paraEnum->nextElement(); uno::Reference const xElem(paraEnum->nextElement(), uno::UNO_QUERY_THROW); return xElem; } uno::Reference SwModelTestBase::getParagraph(int number, const OUString& content) const { uno::Reference 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 xPara(getParagraph(nPara)); uno::Reference properties(xPara, uno::UNO_QUERY); bool isNumber = false; properties->getPropertyValue("NumberingIsNumber") >>= isNumber; if (isNumber) { uno::Reference xLevels( properties->getPropertyValue("NumberingRules"), uno::UNO_QUERY); sal_Int16 nNumberingLevel = -1; properties->getPropertyValue("NumberingLevel") >>= nNumberingLevel; if (nNumberingLevel >= 0 && nNumberingLevel < xLevels->getCount()) { uno::Sequence 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(); } } return nNumberingType; } uno::Reference SwModelTestBase::getParagraphOfText(int number, uno::Reference const& xText, const OUString& content) const { uno::Reference 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 SwModelTestBase::getParagraphAnchoredObject(int const index, uno::Reference const& xPara) const { uno::Reference xContentEnumAccess(xPara, uno::UNO_QUERY); uno::Reference xContentEnum = xContentEnumAccess->createContentEnumeration("com.sun.star.text.TextContent"); for (int i = 1; i < index; ++i) { xContentEnum->nextElement(); } return uno::Reference(xContentEnum->nextElement(), uno::UNO_QUERY); } uno::Reference SwModelTestBase::getRun(uno::Reference const& xParagraph, int number, const OUString& content) const { uno::Reference xRunEnumAccess(xParagraph, uno::UNO_QUERY); uno::Reference xRunEnum = xRunEnumAccess->createEnumeration(); for (int i = 1; i < number; ++i) xRunEnum->nextElement(); uno::Reference 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 const& xRun) const { uno::Reference xContentEnumAccess(xRun, uno::UNO_QUERY); uno::Reference xContentEnum = xContentEnumAccess->createContentEnumeration(""); uno::Reference xFormula(xContentEnum->nextElement(), uno::UNO_QUERY); return getProperty( getProperty>(xFormula, "Model"), "Formula"); } uno::Reference SwModelTestBase::getCell(uno::Reference const& xTableIfc, OUString const& rCell, OUString const& rContent) { uno::Reference const xTable(xTableIfc, uno::UNO_QUERY_THROW); uno::Reference const xCell(xTable->getCellByName(rCell), uno::UNO_SET_THROW); if (!rContent.isEmpty()) { uno::Reference const xCellText(xCell, uno::UNO_QUERY_THROW); CPPUNIT_ASSERT_EQUAL_MESSAGE("cell does not contain expected content", rContent, xCellText->getString()); } return xCell; } uno::Reference SwModelTestBase::getShape(int number) { uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); uno::Reference xShape(xDrawPage->getByIndex(number - 1), uno::UNO_QUERY); return xShape; } uno::Reference SwModelTestBase::getShapeByName(std::u16string_view aName) { uno::Reference xRet; uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xDrawPage = xDrawPageSupplier->getDrawPage(); for (sal_Int32 i = 0; i < xDrawPage->getCount(); ++i) { uno::Reference xShape(xDrawPage->getByIndex(i), uno::UNO_QUERY); if (xShape->getName() == aName) { xRet.set(xShape, uno::UNO_QUERY); break; } } return xRet; } uno::Reference SwModelTestBase::getTextFrameByName(const OUString& aName) { uno::Reference xTextFramesSupplier(mxComponent, uno::UNO_QUERY); uno::Reference xNameAccess = xTextFramesSupplier->getTextFrames(); uno::Reference xShape(xNameAccess->getByName(aName), uno::UNO_QUERY); return xShape; } void SwModelTestBase::setTestInteractionHandler(const char* pPassword, std::vector& rFilterOptions) { OUString sPassword = OUString::createFromAscii(pPassword); rFilterOptions.emplace_back(); xInteractionHandler = rtl::Reference(new TestInteractionHandler(sPassword)); uno::Reference 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 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 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 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 xComponent(xStorable, uno::UNO_QUERY); xComponent->dispose(); mbExported = true; std::vector 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 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 xModel(mxComponent, uno::UNO_QUERY); uno::Reference xTextViewCursorSupplier( xModel->getCurrentController(), uno::UNO_QUERY); uno::Reference xCursor(xTextViewCursorSupplier->getViewCursor(), uno::UNO_QUERY); xCursor->jumpToLastPage(); return xCursor->getPage(); } int SwModelTestBase::getShapes() const { uno::Reference xDrawPageSupplier(mxComponent, uno::UNO_QUERY); uno::Reference 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 SwModelTestBase::parseExportStream(const OUString& url, const OUString& rStreamName) { // Read the stream we're interested in. uno::Reference xNameAccess = packages::zip::ZipFileAccess::createWithURL(comphelper::getComponentContext(m_xSFactory), url); uno::Reference xInputStream(xNameAccess->getByName(rStreamName), uno::UNO_QUERY); CPPUNIT_ASSERT(xInputStream.is()); std::unique_ptr pStream(utl::UcbStreamHelper::CreateStream(xInputStream, true)); return pStream; } xmlDocUniquePtr SwModelTestBase::parseExportInternal(const OUString& url, const OUString& rStreamName) { std::unique_ptr pStream(parseExportStream(url, rStreamName)); xmlDocUniquePtr pXmlDoc = parseXmlStream(pStream.get()); pXmlDoc->name = reinterpret_cast(xmlStrdup( reinterpret_cast(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); return getSwDoc(); } 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); return getSwDoc(); } SwXTextDocument& SwModelTestBase::getSwXTextDocument() { SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); CPPUNIT_ASSERT(pTextDoc); return *pTextDoc; } SwDoc* SwModelTestBase::getSwDoc() { return getSwXTextDocument().GetDocShell()->GetDoc(); } /* vim:set shiftwidth=4 softtabstop=4 expandtab: */