CppunitTest_sw_ooxmlexport10: split in two

it already has 104 tests

Change-Id: Ib3b4bf342af73aaf3c925d79bd0a06cee4853c93
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/150234
Tested-by: Jenkins
Reviewed-by: Xisco Fauli <xiscofauli@libreoffice.org>
This commit is contained in:
Xisco Fauli 2023-04-11 16:12:40 +02:00
parent 9c933a9221
commit 436c280392
4 changed files with 915 additions and 772 deletions

View file

@ -0,0 +1,18 @@
# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*-
#*************************************************************************
#
# 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/.
#
#*************************************************************************
$(eval $(call sw_ooxmlexport_test,19))
$(eval $(call gb_CppunitTest_use_custom_headers,sw_ooxmlexport19,\
officecfg/registry \
))
# vim: set noet sw=4 ts=4:

View file

@ -92,6 +92,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\
CppunitTest_sw_ooxmlexport16 \
CppunitTest_sw_ooxmlexport17 \
CppunitTest_sw_ooxmlexport18 \
CppunitTest_sw_ooxmlexport19 \
CppunitTest_sw_ooxmlexport_template \
CppunitTest_sw_ooxmlfieldexport \
CppunitTest_sw_ooxmllinks \

View file

@ -13,37 +13,26 @@
#include <com/sun/star/awt/FontUnderline.hpp>
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/drawing/EnhancedCustomShapeParameterPair.hpp>
#include <com/sun/star/drawing/XShapes.hpp>
#include <com/sun/star/text/RelOrientation.hpp>
#include <com/sun/star/text/TableColumnSeparator.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <com/sun/star/text/WrapTextMode.hpp>
#include <com/sun/star/text/WritingMode2.hpp>
#include <com/sun/star/text/XFootnote.hpp>
#include <com/sun/star/text/XTextColumns.hpp>
#include <com/sun/star/text/XTextFrame.hpp>
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/text/SizeType.hpp>
#include <com/sun/star/text/XDocumentIndex.hpp>
#include <com/sun/star/style/CaseMap.hpp>
#include <com/sun/star/text/XDocumentIndexesSupplier.hpp>
#include <com/sun/star/text/XTextDocument.hpp>
#include <com/sun/star/text/XTextEmbeddedObjectsSupplier.hpp>
#include <com/sun/star/text/XTextFramesSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
#include <tools/UnitConversion.hxx>
#include <unotools/fltrcfg.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <oox/drawingml/drawingmltypes.hxx>
#include <svx/svdpage.hxx>
#include <drawdoc.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <unotxdoc.hxx>
#include <docsh.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <flyfrms.hxx>
#include <sortedobjs.hxx>
#include <txtfrm.hxx>
class Test : public SwModelTestBase
{
@ -729,761 +718,6 @@ DECLARE_OOXMLEXPORT_TEST(testGroupshapeTrackedchanges, "groupshape-trackedchange
CPPUNIT_ASSERT_EQUAL(OUString(" Inserted"), getRun(xParagraph, 5)->getString());
}
DECLARE_OOXMLEXPORT_TEST(testFdo78939, "fdo78939.docx")
{
// fdo#78939 : LO hanged while opening issue document
// Whenever a para-style was applied to a Numbering format level,
// LO incorrectly also changed the para-style...
// check that file opens and does not hang while opening and also
// check that an incorrect numbering style is not applied ...
CPPUNIT_ASSERT_EQUAL(OUString(), getProperty<OUString>(getParagraph(1), "NumberingStyleName"));
}
DECLARE_OOXMLEXPORT_TEST(testFootnote, "footnote.docx")
{
uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
uno::Reference<text::XTextRange> xFootnote(xFootnotes->getByIndex(0), uno::UNO_QUERY);
OUString aFootnote = xFootnote->getString();
// Ensure there are no additional newlines after "bar".
CPPUNIT_ASSERT(aFootnote.endsWith("bar"));
}
DECLARE_OOXMLEXPORT_TEST(testTableBtlrCenter, "table-btlr-center.docx")
{
// Note that this is btLr text, so layout and doc model horizontal/vertical is the opposite of
// each other.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XCell> xCell = xTable->getCellByName("A2");
// Cell vertical alignment was CENTER, should be NONE.
CPPUNIT_ASSERT_EQUAL(text::VertOrientation::NONE, getProperty<sal_Int16>(xCell, "VertOrient"));
// Cell horizontal alignment should be CENTER.
uno::Reference<text::XText> xCellText(xCell, uno::UNO_QUERY);
auto nActual = getProperty<sal_Int32>(getParagraphOfText(1, xCellText), "ParaAdjust");
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(style::ParagraphAdjust_CENTER), nActual);
}
DECLARE_OOXMLEXPORT_TEST(testFdo80555, "fdo80555.docx")
{
uno::Reference<drawing::XShape> xShape = getShape(1);
// Shape was wrongly placed at X=0, Y=0
CPPUNIT_ASSERT_EQUAL(sal_Int32(3318), xShape->getPosition().X);
CPPUNIT_ASSERT_EQUAL(sal_Int32(247), xShape->getPosition().Y);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf104418)
{
loadAndReload("tdf104418.odt");
// Problem was that <w:hideMark> cell property was ignored.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
// Without the fix in place, this test would have failed with
// - Expected: 750
// - Actual : 1499
CPPUNIT_ASSERT_EQUAL(sal_Int64(750) , getProperty<sal_Int64>(xTableRows->getByIndex(0), "Height"));
}
DECLARE_OOXMLEXPORT_TEST(testHidemark, "hidemark.docx")
{
// Problem was that <w:hideMark> cell property was ignored.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
// Height should be minimal
CPPUNIT_ASSERT_EQUAL(convertTwipToMm100(MINLAY), getProperty<sal_Int64>(xTableRows->getByIndex(1), "Height"));
// Size type was MIN, should be FIX to avoid considering the end of paragraph marker.
CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX, getProperty<sal_Int16>(xTableRows->getByIndex(1), "SizeType"));
//tdf#104876: Width was not recognized during import when table size was 'auto'
CPPUNIT_ASSERT_MESSAGE("table size is less than 7000?",sal_Int32(7000) > getProperty<sal_Int32>(xTextTable, "Width"));
}
DECLARE_OOXMLEXPORT_TEST(testHidemarkb, "tdf99616_hidemarkb.docx")
{
// Problem was that the smallest possible height was forced, not the min specified size.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables( ), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
// Height should be .5cm
CPPUNIT_ASSERT_EQUAL(sal_Int64(501), getProperty<sal_Int64>(xTableRows->getByIndex(1), "Height"));
// Size type was MIN, should be FIX to avoid considering the end of paragraph marker.
CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX, getProperty<sal_Int16>(xTableRows->getByIndex(1), "SizeType"));
}
DECLARE_OOXMLEXPORT_TEST(testBnc891663, "bnc891663.docx")
{
// The image should be inside a cell, so the text in the following cell should be below it.
int imageTop = parseDump("/root/page/body/tab/row[1]/cell[2]/txt[1]/anchored/fly/infos/bounds", "top").toInt32();
int imageHeight = parseDump("/root/page/body/tab/row[1]/cell[2]/txt[1]/anchored/fly/infos/bounds", "height").toInt32();
int textNextRowTop = parseDump("/root/page/body/tab/row[2]/cell[1]/txt[1]/infos/bounds", "top").toInt32();
CPPUNIT_ASSERT( textNextRowTop >= imageTop + imageHeight );
}
DECLARE_OOXMLEXPORT_TEST(testTdf123104, "tdf123104.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XCell> xCell = xTable->getCellByName("E1");
// See SwXCell::getPropertyValue(), we really put 'long' into an Any there.
// Without the accompanying fix in place, this test would have failed with 'Expected: 3;Actual :
// 2', i.e. the vertical merge covered one less cell, resulting in a cell with white background.
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(3), getProperty<tools::Long>(xCell, "RowSpan"));
}
DECLARE_OOXMLEXPORT_TEST(testFdo85542, "fdo85542.docx")
{
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), xBookmarksByIdx->getCount());
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("B1"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("B2"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("B3"));
// B1
uno::Reference<text::XTextContent> xContent1(xBookmarksByName->getByName("B1"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange1 = xContent1->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("ABB"), xRange1->getString());
// B2
uno::Reference<text::XTextContent> xContent2(xBookmarksByName->getByName("B2"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange2 = xContent2->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("BBC"), xRange2->getString());
// B3 -- testing a collapsed bookmark
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName("B3"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
CPPUNIT_ASSERT_EQUAL(xRange3->getString(), OUString());
uno::Reference<text::XText> xText = xRange3->getText( );
uno::Reference<text::XTextCursor> xNeighborhoodCursor = xText->createTextCursor( );
xNeighborhoodCursor->gotoRange(xRange3, false);
xNeighborhoodCursor->goLeft(1, false);
xNeighborhoodCursor->goRight(2, true);
CPPUNIT_ASSERT_EQUAL(OUString("AB"), xNeighborhoodCursor->getString());
}
CPPUNIT_TEST_FIXTURE(Test, testTdf65955)
{
loadAndReload("tdf65955.odt");
CPPUNIT_ASSERT_EQUAL(1, getPages());
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xBookmarksByIdx->getCount());
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("a"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("b"));
// a
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName("a"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
CPPUNIT_ASSERT_EQUAL(xRange3->getString(), OUString());
// b
uno::Reference<text::XTextContent> xContent2(xBookmarksByName->getByName("b"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange2 = xContent2->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("r"), xRange2->getString());
}
CPPUNIT_TEST_FIXTURE(Test, testTdf65955_2)
{
loadAndReload("tdf65955_2.odt");
CPPUNIT_ASSERT_EQUAL(1, getPages());
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xBookmarksByIdx->getCount());
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("test"));
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName("test"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("foo bar"), xRange3->getString());
}
DECLARE_OOXMLEXPORT_TEST(testChtOutlineNumberingOoxml, "chtoutline.docx")
{
static constexpr OUStringLiteral aExpectedNumbering = u"\u7b2c 1 \u7ae0";
uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering),
getProperty<OUString>(xPara, "ListLabelString"));
}
DECLARE_OOXMLEXPORT_TEST(mathtype, "mathtype.docx")
{
uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xEmbeddedObjects(xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY);
// This failed as the Model property was empty.
auto xModel = getProperty< uno::Reference<lang::XServiceInfo> >(xEmbeddedObjects->getByIndex(0), "Model");
CPPUNIT_ASSERT(xModel->supportsService("com.sun.star.formula.FormulaProperties"));
}
CPPUNIT_TEST_FIXTURE(Test, testTdf8255)
{
SwModelTestBase::FlySplitGuard aGuard;
auto verify = [this]() {
// A full-page-wide multi-page floating table should be allowed to split:
uno::Reference<text::XTextFramesSupplier> xDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xFrame(xDocument->getTextFrames()->getByName("Frame1"),
uno::UNO_QUERY);
bool bIsSplitAllowed{};
xFrame->getPropertyValue("IsSplitAllowed") >>= bIsSplitAllowed;
CPPUNIT_ASSERT(bIsSplitAllowed);
};
createSwDoc("tdf8255.docx");
verify();
reload(mpFilter, "tdf8255.docx");
verify();
}
DECLARE_OOXMLEXPORT_TEST(testTdf87460, "tdf87460.docx")
{
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(xTextDocument, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes();
// This was 0: endnote was lost on import.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xEndnotes->getCount());
}
DECLARE_OOXMLEXPORT_TEST(testTdf90611, "tdf90611.docx")
{
uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
uno::Reference<text::XText> xFootnoteText;
xFootnotes->getByIndex(0) >>= xFootnoteText;
// This was 11.
CPPUNIT_ASSERT_EQUAL(10.f, getProperty<float>(getParagraphOfText(1, xFootnoteText), "CharHeight"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf89702, "tdf89702.docx")
{
// Get the first paragraph's numbering style's 2nd level's character style name.
uno::Reference<text::XTextRange> xParagraph = getParagraph(1);
auto xLevels = getProperty< uno::Reference<container::XIndexAccess> >(xParagraph, "NumberingRules");
uno::Sequence<beans::PropertyValue> aLevel;
xLevels->getByIndex(1) >>= aLevel; // 2nd level
OUString aCharStyleName = std::find_if(std::cbegin(aLevel), std::cend(aLevel), [](const beans::PropertyValue& rValue) { return rValue.Name == "CharStyleName"; })->Value.get<OUString>();
// Make sure that the font name is Arial, this was Verdana.
uno::Reference<beans::XPropertySet> xStyle(getStyles("CharacterStyles")->getByName(aCharStyleName), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString("Arial"), getProperty<OUString>(xStyle, "CharFontName"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf86374, "tdf86374.docx")
{
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(), uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTable->getRows();
// btLr text direction was imported as FIX, it should be MIN to have enough space for the additionally entered paragraphs.
CPPUNIT_ASSERT_EQUAL(text::SizeType::MIN, getProperty<sal_Int16>(xTableRows->getByIndex(0), "SizeType"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf87924, "tdf87924.docx")
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY);
comphelper::SequenceAsHashMap aGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
// This was -270, the text rotation angle was set when it should not be rotated.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0), aGeometry["TextPreRotateAngle"].get<sal_Int32>());
}
DECLARE_OOXMLEXPORT_TEST(testIndents, "indents.docx")
{
//expected left margin and first line indent values
static const sal_Int32 indents[] =
{
0, 0,
-2000, 0,
-2000, 1000,
-1000, -1000,
2000, -1000
};
uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(textDocument->getText(), uno::UNO_QUERY);
// list of paragraphs
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
size_t paraIndex = 0;
do
{
uno::Reference<lang::XServiceInfo> xServiceInfo;
if (xParaEnum->nextElement() >>= xServiceInfo)
{
uno::Reference<beans::XPropertySet> const xPropertySet(xServiceInfo, uno::UNO_QUERY_THROW);
sal_Int32 nIndent = 0;
sal_Int32 nFirstLine = 0;
xPropertySet->getPropertyValue("ParaLeftMargin") >>= nIndent;
xPropertySet->getPropertyValue("ParaFirstLineIndent") >>= nFirstLine;
CPPUNIT_ASSERT_EQUAL(indents[paraIndex * 2], nIndent);
CPPUNIT_ASSERT_EQUAL(indents[paraIndex * 2 + 1], nFirstLine);
++paraIndex;
}
} while (xParaEnum->hasMoreElements());
}
DECLARE_OOXMLEXPORT_TEST(testTdf92454, "tdf92454.docx")
{
// The first paragraph had a large indentation / left margin as inheritance
// in Word and Writer works differently, and no direct value was set to be
// explicit.
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(1), uno::UNO_QUERY);
// This was beans::PropertyState_DEFAULT_VALUE.
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, xParagraph->getPropertyState("ParaFirstLineIndent"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf95377, "tdf95377.docx")
{
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(1), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), getProperty<sal_Int32>(xParagraph, "ParaRightMargin"));
xParagraph.set(getParagraph(2), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(-501), getProperty<sal_Int32>(xParagraph, "ParaFirstLineIndent"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(2501), getProperty<sal_Int32>(xParagraph, "ParaLeftMargin"));
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, xParagraph->getPropertyState("ParaFirstLineIndent"));
xParagraph.set(getParagraph(3), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(-250), getProperty<sal_Int32>(xParagraph, "ParaFirstLineIndent"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(250), getProperty<sal_Int32>(xParagraph, "ParaLeftMargin"));
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE, xParagraph->getPropertyState("ParaFirstLineIndent"));
//default style has numbering enabled. Styles inherit numbering unless specifically disabled
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc, "//body/txt/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", 3); //first three paragraphs have numbering
assertXPath(pXmlDoc, "//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", "a.");
assertXPath(pXmlDoc, "//body/txt[2]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", "b.");
assertXPath(pXmlDoc, "//body/txt[3]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", "expand", "c.");
assertXPath(pXmlDoc, "/root/page/body/txt[4]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']", 0); //last paragraph style disables numbering
}
DECLARE_OOXMLEXPORT_TEST(testTdf95376, "tdf95376.docx")
{
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(2), uno::UNO_QUERY);
// This was beans::PropertyState_DIRECT_VALUE: indentation-from-numbering
// did not have priority over indentation-from-paragraph-style, due to a
// filter workaround that's not correct here.
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DEFAULT_VALUE, xParagraph->getPropertyState("ParaFirstLineIndent"));
//tdf#131321 - paragraph styles lost their numbering. Bullet+space inherits WWNum1 from Bullet
uno::Reference<beans::XPropertySet> xStyle(getStyles("ParagraphStyles")->getByName("Bullet+space"), uno::UNO_QUERY);
CPPUNIT_ASSERT(!(getProperty<OUString>(xStyle, "NumberingStyleName")).isEmpty());
}
DECLARE_OOXMLEXPORT_TEST(testTdf92124, "tdf92124.docx")
{
// Get the second paragraph's numbering style's 1st level's suffix.
uno::Reference<text::XTextRange> xParagraph = getParagraph(2);
auto xLevels = getProperty< uno::Reference<container::XIndexAccess> >(xParagraph, "NumberingRules");
uno::Sequence<beans::PropertyValue> aLevel;
xLevels->getByIndex(0) >>= aLevel; // 1st level
OUString aSuffix = std::find_if(std::cbegin(aLevel), std::cend(aLevel), [](const beans::PropertyValue& rValue) { return rValue.Name == "Suffix"; })->Value.get<OUString>();
// Make sure it's empty as the source document contains <w:suff w:val="nothing"/>.
CPPUNIT_ASSERT(aSuffix.isEmpty());
}
DECLARE_OOXMLEXPORT_TEST(testTdf90153, "tdf90153.docx")
{
// This was at-para, so the line-level VertOrientRelation was lost, resulting in an incorrect vertical position.
CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER, getProperty<text::TextContentAnchorType>(getShape(1), "AnchorType"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf93919, "tdf93919.docx")
{
// This was 0, left margin was not inherited from the list style.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1270), getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf91417, "tdf91417.docx")
{
// The first paragraph should contain a link to "http://www.google.com/"
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextCursor> xTextCursor = xTextDocument->getText()->createTextCursor( );
uno::Reference<beans::XPropertySet> xCursorProps(xTextCursor, uno::UNO_QUERY);
OUString aValue;
xCursorProps->getPropertyValue("HyperLinkURL") >>= aValue;
CPPUNIT_ASSERT_EQUAL(OUString("http://www.google.com/"), aValue);
}
DECLARE_OOXMLEXPORT_TEST(testTdf90810, "tdf90810short.docx")
{
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XFootnotesSupplier> xFootnoteSupp(xTextDocument, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xFootnoteIdxAcc = xFootnoteSupp->getFootnotes();
uno::Reference<text::XFootnote> xFootnote(xFootnoteIdxAcc->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XText> xFootnoteText(xFootnote, uno::UNO_QUERY);
OUString sFootnoteText = xFootnoteText->getString();
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(89), sFootnoteText.getLength());
}
DECLARE_OOXMLEXPORT_TEST(testTdf89165, "tdf89165.docx")
{
// This must not hang in layout
}
DECLARE_OOXMLEXPORT_TEST(testTdf95777, "tdf95777.docx")
{
// This must not fail on open
}
CPPUNIT_TEST_FIXTURE(Test, testTdf94374)
{
createSwDoc("hello.docx");
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextRange> xText = xTextDocument->getText();
uno::Reference<text::XTextRange> xEnd = xText->getEnd();
// This failed: it wasn't possible to insert a DOCX document into an existing Writer one.
paste(u"ooxmlexport/data/tdf94374.docx", "com.sun.star.comp.Writer.WriterFilter", xEnd);
}
DECLARE_OOXMLEXPORT_TEST(testTdf83300, "tdf83300.docx")
{
// tdf#143722: This was 'TOC Heading', upon updating a TOC the heading replaced its Word-default blue + Calibri style
// with a Writer-default black + Liberation Sans one
CPPUNIT_ASSERT_EQUAL(OUString("Contents Heading"), getProperty<OUString>(getParagraph(1), "ParaStyleName"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf78902, "tdf78902.docx")
{
// This hung in layout.
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
DECLARE_OOXMLEXPORT_TEST(testTdf95775, "tdf95775.docx")
{
// This must not fail in layout
}
DECLARE_OOXMLEXPORT_TEST(testTdf92157, "tdf92157.docx")
{
// A graphic with dimensions 0,0 should not fail on load
// Additionally, the bookmark names should not change (they got a "1" appended when copied)
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("referentiegegevens"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("referentiegegevens_bk"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf97417, "section_break_numbering.docx")
{
uno::Reference<beans::XPropertySet> xProps(getParagraph(1), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("1st page: first paragraph erroneous numbering",
!xProps->getPropertyValue("NumberingRules").hasValue());
// paragraph with numbering and section break was removed by writerfilter
// but its numbering was copied to all following paragraphs
CPPUNIT_ASSERT_MESSAGE("2nd page: first paragraph missing numbering",
getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(2), "NumberingRules").is());
xProps = uno::Reference<beans::XPropertySet>(getParagraph(3), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("2nd page: second paragraph erroneous numbering",
!xProps->getPropertyValue("NumberingRules").hasValue());
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
DECLARE_OOXMLEXPORT_TEST(testTdf94043, "tdf94043.docx")
{
auto xTextSection = getProperty< uno::Reference<beans::XPropertySet> >(getParagraph(2), "TextSection");
auto xTextColumns = getProperty< uno::Reference<text::XTextColumns> >(xTextSection, "TextColumns");
// This was 0, the separator line was not visible due to 0 width.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), getProperty<sal_Int32>(xTextColumns, "SeparatorLineWidth"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf95213, "tdf95213.docx")
{
// Get the second paragraph's numbering style's 2nd level's character style name.
uno::Reference<text::XTextRange> xParagraph = getParagraph(2);
auto xLevels = getProperty< uno::Reference<container::XIndexAccess> >(xParagraph, "NumberingRules");
uno::Sequence<beans::PropertyValue> aLevel;
xLevels->getByIndex(1) >>= aLevel; // 2nd level
OUString aName = std::find_if(std::cbegin(aLevel), std::cend(aLevel), [](const beans::PropertyValue& rValue) { return rValue.Name == "CharStyleName"; })->Value.get<OUString>();
uno::Reference<beans::XPropertySet> xStyle(getStyles("CharacterStyles")->getByName(aName), uno::UNO_QUERY);
// This was awt::FontWeight::BOLD.
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xStyle, "CharWeight"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf97371, "tdf97371.docx")
{
SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument *>(mxComponent.get());
CPPUNIT_ASSERT(pTextDoc);
SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
SdrObject* pShape = pPage->GetObj(0);
SdrObject* pTextBox = pPage->GetObj(1);
tools::Long nDiff = std::abs(pShape->GetSnapRect().Top() - pTextBox->GetSnapRect().Top());
// The top of the two shapes were 410 and 3951, now it should be 3950 and 3951.
CPPUNIT_ASSERT(nDiff < 10);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf99140)
{
SwModelTestBase::FlySplitGuard aGuard;
auto verify = [this]() {
// A multi-page floating table appeared only on the first page.
SwDoc* pDoc = getSwDoc();
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
CPPUNIT_ASSERT(pPage1);
const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
CPPUNIT_ASSERT(pPage1Fly);
SwFrame* pTab1 = pPage1Fly->GetLower();
// This was text::HoriOrientation::NONE, the second table was too wide due to this.
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(9622), pTab1->getFrameArea().Width());
SwFrame* pRow1 = pTab1->GetLower();
SwFrame* pCell1 = pRow1->GetLower();
auto pText1 = dynamic_cast<SwTextFrame*>(pCell1->GetLower());
CPPUNIT_ASSERT(pText1);
CPPUNIT_ASSERT_EQUAL(OUString("Table2:A1"), pText1->GetText());
auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
CPPUNIT_ASSERT(pPage2);
const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
auto pPage2Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage2Objs[0]);
CPPUNIT_ASSERT(pPage2Fly);
SwFrame* pTab2 = pPage2Fly->GetLower();
SwFrame* pRow2 = pTab2->GetLower();
SwFrame* pCell2 = pRow2->GetLower();
auto pText2 = dynamic_cast<SwTextFrame*>(pCell2->GetLower());
CPPUNIT_ASSERT(pText2);
CPPUNIT_ASSERT_EQUAL(OUString("Table2:A2"), pText2->GetText());
};
createSwDoc("tdf99140.docx");
verify();
reload(mpFilter, "tdf99140.docx");
verify();
}
CPPUNIT_TEST_FIXTURE(Test, testTableMarginAdjustment)
{
loadAndReload("table.fodt");
// Writer, (new) Word: margin 0 means table border starts at 0
// (old) Word: margin 0 means paragraph in table starts at 0
auto const xTable(getParagraphOrTable(1));
// shifted very slightly to account for half of the thin border width, so 4, not 0.
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), getProperty<sal_Int32>(xTable, "LeftMargin"));
// Now that compatibilityMode is set to 2013's 15 (new), expect the new values,
// since LO is exporting in the NEW way now instead of the OLD way.
// This was 55 when using 2007's compatibilityMode of 12 (old)
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "type", "dxa");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "w", "0");
// tdf#143982: automatic tables should export as something better than just left-and-size
CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xTable, "RelativeWidth"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf119760_tableInTablePosition, "tdf119760_tableInTablePosition.docx")
{
if ( isExported() )
{
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tr[1]/w:tc[1]/w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "type", "dxa");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tr[1]/w:tc[1]/w:tbl[1]//w:tblPr[1]/w:tblInd[1]", "w", "0");
}
uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
uno::Reference< container::XIndexAccess > xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
uno::Reference< text::XTextTable > xTable( xTables->getByIndex(0), uno::UNO_QUERY );
// For compatibilityMode 15: margin 0 means table border starts at 0,
// shifted to account for half of the thick border width, so 106, not 0.
CPPUNIT_ASSERT_EQUAL(sal_Int32(106), getProperty<sal_Int32>(xTable, "LeftMargin"));
}
DECLARE_OOXMLEXPORT_TEST( testTableCellMargin, "table-cell-margin.docx" )
{
sal_Int32 const cellLeftMarginFromOffice[] = { 250, 100, 0, 0 };
uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
uno::Reference< container::XIndexAccess > xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
for ( int i = 0; i < 4; i++ )
{
uno::Reference< text::XTextTable > xTable1( xTables->getByIndex( i ), uno::UNO_QUERY );
// Verify left margin of 1st cell :
// * Office left margins are measured relative to the right of the border
// * LO left spacing is measured from the center of the border
uno::Reference< table::XCell > xCell = xTable1->getCellByName( "A1" );
uno::Reference< beans::XPropertySet > xPropSet( xCell, uno::UNO_QUERY_THROW );
sal_Int32 aLeftMargin = -1;
xPropSet->getPropertyValue( "LeftBorderDistance" ) >>= aLeftMargin;
uno::Any aLeftBorder = xPropSet->getPropertyValue( "LeftBorder" );
table::BorderLine2 aLeftBorderLine;
aLeftBorder >>= aLeftBorderLine;
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Incorrect left spacing computed from docx cell margin",
cellLeftMarginFromOffice[i], aLeftMargin - 0.5 * aLeftBorderLine.LineWidth, 1 );
// The 'a' in the fourth table should not be partly hidden by the border
if ( i == 3 )
{
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect cell left padding",
0.5 * aLeftBorderLine.LineWidth, aLeftMargin, 1);
// tdf#119885: cell's edit area must touch right border
sal_Int32 aRightMargin = -1;
xPropSet->getPropertyValue("RightBorderDistance") >>= aRightMargin;
uno::Any aRightBorder = xPropSet->getPropertyValue("RightBorder");
table::BorderLine2 aRightBorderLine;
aRightBorder >>= aRightBorderLine;
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect cell right padding",
0.5 * aRightBorderLine.LineWidth, aRightMargin, 1);
}
}
}
CPPUNIT_TEST_FIXTURE(Test, TestPuzzleExport)
{
loadAndReload("TestPuzzleExport.odt");
// See tdf#148342 for details
// Get the doc
uno::Reference< text::XTextDocument > xTextDoc(mxComponent, uno::UNO_QUERY_THROW);
auto pSwDoc = dynamic_cast<SwXTextDocument*>(xTextDoc.get());
CPPUNIT_ASSERT(pSwDoc);
// Create a metafile
auto pMeta = pSwDoc->GetDocShell()->GetPreviewMetaFile();
CPPUNIT_ASSERT(pMeta);
MetafileXmlDump aDumper;
auto pMetaXml = dumpAndParse(aDumper, *pMeta);
CPPUNIT_ASSERT(pMetaXml);
// After parsing check that node...
auto pXNode = getXPathNode(pMetaXml, "/metafile/push/push/push/push[4]/push/push/polypolygon/polygon");
CPPUNIT_ASSERT(pXNode);
auto pNode = pXNode->nodesetval->nodeTab[0];
CPPUNIT_ASSERT(pNode);
auto it = pNode->children;
int nCount = 0;
// .. and count the children
while (it != nullptr)
{
nCount++;
it = it->next;
}
// In case of puzzle there will be so many... Without the fix there was a rectangle with 4 points.
CPPUNIT_ASSERT_GREATER(300, nCount);
}
// tdf#106742 for DOCX with compatibility level <= 14 (MS Word up to and incl. ver.2010), we should use cell margins when calculating table left border position
DECLARE_OOXMLEXPORT_TEST( testTablePosition14, "table-position-14.docx")
{
sal_Int32 const aXCoordsFromOffice[] = { 2500, -1000, 0, 0 };
uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
uno::Reference< frame::XModel > xModel( mxComponent, uno::UNO_QUERY );
uno::Reference< container::XIndexAccess > xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
for ( int i = 0; i < 4; i++ )
{
uno::Reference< text::XTextTable > xTable1( xTables->getByIndex( i ), uno::UNO_QUERY );
// Verify X coord
uno::Reference< view::XSelectionSupplier > xCtrl( xModel->getCurrentController(), uno::UNO_QUERY );
xCtrl->select( uno::Any( xTable1 ) );
uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupplier( xCtrl, uno::UNO_QUERY );
uno::Reference< text::XTextViewCursor > xCursor = xTextViewCursorSupplier->getViewCursor();
awt::Point pos = xCursor->getPosition();
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Incorrect X coord computed from docx",
aXCoordsFromOffice[i], pos.X, 1 );
}
}
// tdf#106742 for DOCX with compatibility level > 14 (MS Word since ver.2013),
// we should NOT use cell margins when calculating table left border position. But we do need to use border width.
DECLARE_OOXMLEXPORT_TEST( testTablePosition15, "table-position-15.docx" )
{
sal_Int32 const aXCoordsFromOffice[] = { 2751, -899, 1, 212 };
uno::Reference< text::XTextTablesSupplier > xTablesSupplier( mxComponent, uno::UNO_QUERY );
uno::Reference< frame::XModel > xModel( mxComponent, uno::UNO_QUERY );
uno::Reference< container::XIndexAccess > xTables( xTablesSupplier->getTextTables(), uno::UNO_QUERY );
for ( int i = 0; i < 4; i++ )
{
uno::Reference< text::XTextTable > xTable1( xTables->getByIndex( i ), uno::UNO_QUERY );
// Verify X coord
uno::Reference< view::XSelectionSupplier > xCtrl( xModel->getCurrentController(), uno::UNO_QUERY );
xCtrl->select( uno::Any( xTable1 ) );
uno::Reference< text::XTextViewCursorSupplier > xTextViewCursorSupplier( xCtrl, uno::UNO_QUERY );
uno::Reference< text::XTextViewCursor > xCursor = xTextViewCursorSupplier->getViewCursor();
awt::Point pos = xCursor->getPosition();
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( "Incorrect X coord computed from docx",
aXCoordsFromOffice[i], pos.X, 1 );
}
}
DECLARE_OOXMLEXPORT_TEST( testTdf107359, "tdf107359-char-pitch.docx" )
{
uno::Reference<beans::XPropertySet> xPropertySet(getStyles("PageStyles")->getByName("Standard"), uno::UNO_QUERY);
bool bGridSnapToChars;
xPropertySet->getPropertyValue("GridSnapToChars") >>= bGridSnapToChars;
CPPUNIT_ASSERT_EQUAL( false, bGridSnapToChars );
sal_Int32 nRubyHeight;
xPropertySet->getPropertyValue("GridRubyHeight") >>= nRubyHeight;
CPPUNIT_ASSERT_EQUAL( sal_Int32(0), nRubyHeight );
sal_Int32 nBaseHeight;
xPropertySet->getPropertyValue("GridBaseHeight") >>= nBaseHeight;
CPPUNIT_ASSERT_EQUAL( sal_Int32(convertTwipToMm100(18 * 20)), nBaseHeight );
sal_Int32 nBaseWidth;
xPropertySet->getPropertyValue("GridBaseWidth") >>= nBaseWidth;
CPPUNIT_ASSERT_EQUAL( sal_Int32(convertTwipToMm100(24 * 20)), nBaseWidth );
}
CPPUNIT_TEST_FIXTURE(Test, testTdf77236_MissingSolidFill)
{
loadAndSave("tdf77236_MissingSolidFill.docx");
// tdf#77236: solidFill of VML shape was not exported if the colors of line and style were the same
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
assertXPath(pXmlDoc, "//mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:ln/a:solidFill", 1);
}
DECLARE_OOXMLEXPORT_TEST(testTdf105875_VmlShapeRotationWithFlip, "tdf105875_VmlShapeRotationWithFlip.docx")
{
// tdf#105875: check whether the rotation of the VML bezier shape is ok (with flip too)
// TODO: fix export too
if (isExported())
return;
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>());
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(2), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(220 * 100), xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(), 1);
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(3), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(320 * 100), xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(), 1);
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(4), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(140 * 100), xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(), 1);
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(5), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(40 * 100), xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(), 1);
}
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

View file

@ -0,0 +1,890 @@
/* -*- 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/awt/FontWeight.hpp>
#include <com/sun/star/text/VertOrientation.hpp>
#include <com/sun/star/text/XFootnote.hpp>
#include <com/sun/star/text/XTextColumns.hpp>
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/view/XSelectionSupplier.hpp>
#include <com/sun/star/style/ParagraphAdjust.hpp>
#include <com/sun/star/text/SizeType.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <tools/UnitConversion.hxx>
#include <comphelper/sequenceashashmap.hxx>
#include <svx/svdpage.hxx>
#include <drawdoc.hxx>
#include <IDocumentDrawModelAccess.hxx>
#include <unotxdoc.hxx>
#include <docsh.hxx>
#include <IDocumentLayoutAccess.hxx>
#include <rootfrm.hxx>
#include <pagefrm.hxx>
#include <flyfrms.hxx>
#include <sortedobjs.hxx>
#include <txtfrm.hxx>
class Test : public SwModelTestBase
{
public:
Test()
: SwModelTestBase("/sw/qa/extras/ooxmlexport/data/", "Office Open XML Text")
{
}
};
DECLARE_OOXMLEXPORT_TEST(testFdo78939, "fdo78939.docx")
{
// fdo#78939 : LO hanged while opening issue document
// Whenever a para-style was applied to a Numbering format level,
// LO incorrectly also changed the para-style...
// check that file opens and does not hang while opening and also
// check that an incorrect numbering style is not applied ...
CPPUNIT_ASSERT_EQUAL(OUString(), getProperty<OUString>(getParagraph(1), "NumberingStyleName"));
}
DECLARE_OOXMLEXPORT_TEST(testFootnote, "footnote.docx")
{
uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
uno::Reference<text::XTextRange> xFootnote(xFootnotes->getByIndex(0), uno::UNO_QUERY);
OUString aFootnote = xFootnote->getString();
// Ensure there are no additional newlines after "bar".
CPPUNIT_ASSERT(aFootnote.endsWith("bar"));
}
DECLARE_OOXMLEXPORT_TEST(testTableBtlrCenter, "table-btlr-center.docx")
{
// Note that this is btLr text, so layout and doc model horizontal/vertical is the opposite of
// each other.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XCell> xCell = xTable->getCellByName("A2");
// Cell vertical alignment was CENTER, should be NONE.
CPPUNIT_ASSERT_EQUAL(text::VertOrientation::NONE, getProperty<sal_Int16>(xCell, "VertOrient"));
// Cell horizontal alignment should be CENTER.
uno::Reference<text::XText> xCellText(xCell, uno::UNO_QUERY);
auto nActual = getProperty<sal_Int32>(getParagraphOfText(1, xCellText), "ParaAdjust");
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(style::ParagraphAdjust_CENTER), nActual);
}
DECLARE_OOXMLEXPORT_TEST(testFdo80555, "fdo80555.docx")
{
uno::Reference<drawing::XShape> xShape = getShape(1);
// Shape was wrongly placed at X=0, Y=0
CPPUNIT_ASSERT_EQUAL(sal_Int32(3318), xShape->getPosition().X);
CPPUNIT_ASSERT_EQUAL(sal_Int32(247), xShape->getPosition().Y);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf104418)
{
loadAndReload("tdf104418.odt");
// Problem was that <w:hideMark> cell property was ignored.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
// Without the fix in place, this test would have failed with
// - Expected: 750
// - Actual : 1499
CPPUNIT_ASSERT_EQUAL(sal_Int64(750),
getProperty<sal_Int64>(xTableRows->getByIndex(0), "Height"));
}
DECLARE_OOXMLEXPORT_TEST(testHidemark, "hidemark.docx")
{
// Problem was that <w:hideMark> cell property was ignored.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
// Height should be minimal
CPPUNIT_ASSERT_EQUAL(convertTwipToMm100(MINLAY),
getProperty<sal_Int64>(xTableRows->getByIndex(1), "Height"));
// Size type was MIN, should be FIX to avoid considering the end of paragraph marker.
CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX,
getProperty<sal_Int16>(xTableRows->getByIndex(1), "SizeType"));
//tdf#104876: Width was not recognized during import when table size was 'auto'
CPPUNIT_ASSERT_MESSAGE("table size is less than 7000?",
sal_Int32(7000) > getProperty<sal_Int32>(xTextTable, "Width"));
}
DECLARE_OOXMLEXPORT_TEST(testHidemarkb, "tdf99616_hidemarkb.docx")
{
// Problem was that the smallest possible height was forced, not the min specified size.
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTextTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTextTable->getRows();
// Height should be .5cm
CPPUNIT_ASSERT_EQUAL(sal_Int64(501),
getProperty<sal_Int64>(xTableRows->getByIndex(1), "Height"));
// Size type was MIN, should be FIX to avoid considering the end of paragraph marker.
CPPUNIT_ASSERT_EQUAL(text::SizeType::FIX,
getProperty<sal_Int16>(xTableRows->getByIndex(1), "SizeType"));
}
DECLARE_OOXMLEXPORT_TEST(testBnc891663, "bnc891663.docx")
{
// The image should be inside a cell, so the text in the following cell should be below it.
int imageTop
= parseDump("/root/page/body/tab/row[1]/cell[2]/txt[1]/anchored/fly/infos/bounds", "top")
.toInt32();
int imageHeight
= parseDump("/root/page/body/tab/row[1]/cell[2]/txt[1]/anchored/fly/infos/bounds", "height")
.toInt32();
int textNextRowTop
= parseDump("/root/page/body/tab/row[2]/cell[1]/txt[1]/infos/bounds", "top").toInt32();
CPPUNIT_ASSERT(textNextRowTop >= imageTop + imageHeight);
}
DECLARE_OOXMLEXPORT_TEST(testTdf123104, "tdf123104.docx")
{
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XCell> xCell = xTable->getCellByName("E1");
// See SwXCell::getPropertyValue(), we really put 'long' into an Any there.
// Without the accompanying fix in place, this test would have failed with 'Expected: 3;Actual :
// 2', i.e. the vertical merge covered one less cell, resulting in a cell with white background.
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(3), getProperty<tools::Long>(xCell, "RowSpan"));
}
DECLARE_OOXMLEXPORT_TEST(testFdo85542, "fdo85542.docx")
{
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(),
uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(3), xBookmarksByIdx->getCount());
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("B1"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("B2"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("B3"));
// B1
uno::Reference<text::XTextContent> xContent1(xBookmarksByName->getByName("B1"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange1 = xContent1->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("ABB"), xRange1->getString());
// B2
uno::Reference<text::XTextContent> xContent2(xBookmarksByName->getByName("B2"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange2 = xContent2->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("BBC"), xRange2->getString());
// B3 -- testing a collapsed bookmark
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName("B3"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
CPPUNIT_ASSERT_EQUAL(xRange3->getString(), OUString());
uno::Reference<text::XText> xText = xRange3->getText();
uno::Reference<text::XTextCursor> xNeighborhoodCursor = xText->createTextCursor();
xNeighborhoodCursor->gotoRange(xRange3, false);
xNeighborhoodCursor->goLeft(1, false);
xNeighborhoodCursor->goRight(2, true);
CPPUNIT_ASSERT_EQUAL(OUString("AB"), xNeighborhoodCursor->getString());
}
CPPUNIT_TEST_FIXTURE(Test, testTdf65955)
{
loadAndReload("tdf65955.odt");
CPPUNIT_ASSERT_EQUAL(1, getPages());
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(),
uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2), xBookmarksByIdx->getCount());
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("a"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("b"));
// a
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName("a"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
CPPUNIT_ASSERT_EQUAL(xRange3->getString(), OUString());
// b
uno::Reference<text::XTextContent> xContent2(xBookmarksByName->getByName("b"), uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange2 = xContent2->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("r"), xRange2->getString());
}
CPPUNIT_TEST_FIXTURE(Test, testTdf65955_2)
{
loadAndReload("tdf65955_2.odt");
CPPUNIT_ASSERT_EQUAL(1, getPages());
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xBookmarksByIdx(xBookmarksSupplier->getBookmarks(),
uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xBookmarksByIdx->getCount());
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("test"));
uno::Reference<text::XTextContent> xContent3(xBookmarksByName->getByName("test"),
uno::UNO_QUERY);
uno::Reference<text::XTextRange> xRange3 = xContent3->getAnchor();
CPPUNIT_ASSERT_EQUAL(OUString("foo bar"), xRange3->getString());
}
DECLARE_OOXMLEXPORT_TEST(testChtOutlineNumberingOoxml, "chtoutline.docx")
{
static constexpr OUStringLiteral aExpectedNumbering = u"\u7b2c 1 \u7ae0";
uno::Reference<beans::XPropertySet> xPara(getParagraph(1), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString(aExpectedNumbering),
getProperty<OUString>(xPara, "ListLabelString"));
}
DECLARE_OOXMLEXPORT_TEST(mathtype, "mathtype.docx")
{
uno::Reference<text::XTextEmbeddedObjectsSupplier> xTextEmbeddedObjectsSupplier(mxComponent,
uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xEmbeddedObjects(
xTextEmbeddedObjectsSupplier->getEmbeddedObjects(), uno::UNO_QUERY);
// This failed as the Model property was empty.
auto xModel
= getProperty<uno::Reference<lang::XServiceInfo>>(xEmbeddedObjects->getByIndex(0), "Model");
CPPUNIT_ASSERT(xModel->supportsService("com.sun.star.formula.FormulaProperties"));
}
CPPUNIT_TEST_FIXTURE(Test, testTdf8255)
{
SwModelTestBase::FlySplitGuard aGuard;
auto verify = [this]() {
// A full-page-wide multi-page floating table should be allowed to split:
uno::Reference<text::XTextFramesSupplier> xDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<beans::XPropertySet> xFrame(xDocument->getTextFrames()->getByName("Frame1"),
uno::UNO_QUERY);
bool bIsSplitAllowed{};
xFrame->getPropertyValue("IsSplitAllowed") >>= bIsSplitAllowed;
CPPUNIT_ASSERT(bIsSplitAllowed);
};
createSwDoc("tdf8255.docx");
verify();
reload(mpFilter, "tdf8255.docx");
verify();
}
DECLARE_OOXMLEXPORT_TEST(testTdf87460, "tdf87460.docx")
{
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XEndnotesSupplier> xEndnotesSupplier(xTextDocument, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xEndnotes = xEndnotesSupplier->getEndnotes();
// This was 0: endnote was lost on import.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1), xEndnotes->getCount());
}
DECLARE_OOXMLEXPORT_TEST(testTdf90611, "tdf90611.docx")
{
uno::Reference<text::XFootnotesSupplier> xFootnotesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xFootnotes = xFootnotesSupplier->getFootnotes();
uno::Reference<text::XText> xFootnoteText;
xFootnotes->getByIndex(0) >>= xFootnoteText;
// This was 11.
CPPUNIT_ASSERT_EQUAL(10.f,
getProperty<float>(getParagraphOfText(1, xFootnoteText), "CharHeight"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf89702, "tdf89702.docx")
{
// Get the first paragraph's numbering style's 2nd level's character style name.
uno::Reference<text::XTextRange> xParagraph = getParagraph(1);
auto xLevels
= getProperty<uno::Reference<container::XIndexAccess>>(xParagraph, "NumberingRules");
uno::Sequence<beans::PropertyValue> aLevel;
xLevels->getByIndex(1) >>= aLevel; // 2nd level
OUString aCharStyleName = std::find_if(std::cbegin(aLevel), std::cend(aLevel),
[](const beans::PropertyValue& rValue) {
return rValue.Name == "CharStyleName";
})
->Value.get<OUString>();
// Make sure that the font name is Arial, this was Verdana.
uno::Reference<beans::XPropertySet> xStyle(
getStyles("CharacterStyles")->getByName(aCharStyleName), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(OUString("Arial"), getProperty<OUString>(xStyle, "CharFontName"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf86374, "tdf86374.docx")
{
uno::Reference<text::XTextTablesSupplier> xTextTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTextTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
uno::Reference<table::XTableRows> xTableRows = xTable->getRows();
// btLr text direction was imported as FIX, it should be MIN to have enough space for the additionally entered paragraphs.
CPPUNIT_ASSERT_EQUAL(text::SizeType::MIN,
getProperty<sal_Int16>(xTableRows->getByIndex(0), "SizeType"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf87924, "tdf87924.docx")
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY);
comphelper::SequenceAsHashMap aGeometry(xPropertySet->getPropertyValue("CustomShapeGeometry"));
// This was -270, the text rotation angle was set when it should not be rotated.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(0),
aGeometry["TextPreRotateAngle"].get<sal_Int32>());
}
DECLARE_OOXMLEXPORT_TEST(testIndents, "indents.docx")
{
//expected left margin and first line indent values
static const sal_Int32 indents[] = { 0, 0, -2000, 0, -2000, 1000, -1000, -1000, 2000, -1000 };
uno::Reference<text::XTextDocument> textDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XEnumerationAccess> xParaEnumAccess(textDocument->getText(),
uno::UNO_QUERY);
// list of paragraphs
uno::Reference<container::XEnumeration> xParaEnum = xParaEnumAccess->createEnumeration();
size_t paraIndex = 0;
do
{
uno::Reference<lang::XServiceInfo> xServiceInfo;
if (xParaEnum->nextElement() >>= xServiceInfo)
{
uno::Reference<beans::XPropertySet> const xPropertySet(xServiceInfo,
uno::UNO_QUERY_THROW);
sal_Int32 nIndent = 0;
sal_Int32 nFirstLine = 0;
xPropertySet->getPropertyValue("ParaLeftMargin") >>= nIndent;
xPropertySet->getPropertyValue("ParaFirstLineIndent") >>= nFirstLine;
CPPUNIT_ASSERT_EQUAL(indents[paraIndex * 2], nIndent);
CPPUNIT_ASSERT_EQUAL(indents[paraIndex * 2 + 1], nFirstLine);
++paraIndex;
}
} while (xParaEnum->hasMoreElements());
}
DECLARE_OOXMLEXPORT_TEST(testTdf92454, "tdf92454.docx")
{
// The first paragraph had a large indentation / left margin as inheritance
// in Word and Writer works differently, and no direct value was set to be
// explicit.
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(1), uno::UNO_QUERY);
// This was beans::PropertyState_DEFAULT_VALUE.
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE,
xParagraph->getPropertyState("ParaFirstLineIndent"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf95377, "tdf95377.docx")
{
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(1), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(1000), getProperty<sal_Int32>(xParagraph, "ParaRightMargin"));
xParagraph.set(getParagraph(2), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(-501),
getProperty<sal_Int32>(xParagraph, "ParaFirstLineIndent"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(2501), getProperty<sal_Int32>(xParagraph, "ParaLeftMargin"));
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE,
xParagraph->getPropertyState("ParaFirstLineIndent"));
xParagraph.set(getParagraph(3), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(-250),
getProperty<sal_Int32>(xParagraph, "ParaFirstLineIndent"));
CPPUNIT_ASSERT_EQUAL(sal_Int32(250), getProperty<sal_Int32>(xParagraph, "ParaLeftMargin"));
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DIRECT_VALUE,
xParagraph->getPropertyState("ParaFirstLineIndent"));
//default style has numbering enabled. Styles inherit numbering unless specifically disabled
xmlDocUniquePtr pXmlDoc = parseLayoutDump();
assertXPath(pXmlDoc,
"//body/txt/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
3); //first three paragraphs have numbering
assertXPath(pXmlDoc,
"//body/txt[1]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
"expand", "a.");
assertXPath(pXmlDoc,
"//body/txt[2]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
"expand", "b.");
assertXPath(pXmlDoc,
"//body/txt[3]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
"expand", "c.");
assertXPath(
pXmlDoc,
"/root/page/body/txt[4]/SwParaPortion/SwLineLayout/child::*[@type='PortionType::Number']",
0); //last paragraph style disables numbering
}
DECLARE_OOXMLEXPORT_TEST(testTdf95376, "tdf95376.docx")
{
uno::Reference<beans::XPropertyState> xParagraph(getParagraph(2), uno::UNO_QUERY);
// This was beans::PropertyState_DIRECT_VALUE: indentation-from-numbering
// did not have priority over indentation-from-paragraph-style, due to a
// filter workaround that's not correct here.
CPPUNIT_ASSERT_EQUAL(beans::PropertyState_DEFAULT_VALUE,
xParagraph->getPropertyState("ParaFirstLineIndent"));
//tdf#131321 - paragraph styles lost their numbering. Bullet+space inherits WWNum1 from Bullet
uno::Reference<beans::XPropertySet> xStyle(
getStyles("ParagraphStyles")->getByName("Bullet+space"), uno::UNO_QUERY);
CPPUNIT_ASSERT(!(getProperty<OUString>(xStyle, "NumberingStyleName")).isEmpty());
}
DECLARE_OOXMLEXPORT_TEST(testTdf92124, "tdf92124.docx")
{
// Get the second paragraph's numbering style's 1st level's suffix.
uno::Reference<text::XTextRange> xParagraph = getParagraph(2);
auto xLevels
= getProperty<uno::Reference<container::XIndexAccess>>(xParagraph, "NumberingRules");
uno::Sequence<beans::PropertyValue> aLevel;
xLevels->getByIndex(0) >>= aLevel; // 1st level
OUString aSuffix
= std::find_if(std::cbegin(aLevel), std::cend(aLevel),
[](const beans::PropertyValue& rValue) { return rValue.Name == "Suffix"; })
->Value.get<OUString>();
// Make sure it's empty as the source document contains <w:suff w:val="nothing"/>.
CPPUNIT_ASSERT(aSuffix.isEmpty());
}
DECLARE_OOXMLEXPORT_TEST(testTdf90153, "tdf90153.docx")
{
// This was at-para, so the line-level VertOrientRelation was lost, resulting in an incorrect vertical position.
CPPUNIT_ASSERT_EQUAL(text::TextContentAnchorType_AT_CHARACTER,
getProperty<text::TextContentAnchorType>(getShape(1), "AnchorType"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf93919, "tdf93919.docx")
{
// This was 0, left margin was not inherited from the list style.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(1270),
getProperty<sal_Int32>(getParagraph(1), "ParaLeftMargin"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf91417, "tdf91417.docx")
{
// The first paragraph should contain a link to "http://www.google.com/"
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextCursor> xTextCursor = xTextDocument->getText()->createTextCursor();
uno::Reference<beans::XPropertySet> xCursorProps(xTextCursor, uno::UNO_QUERY);
OUString aValue;
xCursorProps->getPropertyValue("HyperLinkURL") >>= aValue;
CPPUNIT_ASSERT_EQUAL(OUString("http://www.google.com/"), aValue);
}
DECLARE_OOXMLEXPORT_TEST(testTdf90810, "tdf90810short.docx")
{
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XFootnotesSupplier> xFootnoteSupp(xTextDocument, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xFootnoteIdxAcc = xFootnoteSupp->getFootnotes();
uno::Reference<text::XFootnote> xFootnote(xFootnoteIdxAcc->getByIndex(0), uno::UNO_QUERY);
uno::Reference<text::XText> xFootnoteText(xFootnote, uno::UNO_QUERY);
OUString sFootnoteText = xFootnoteText->getString();
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(89), sFootnoteText.getLength());
}
DECLARE_OOXMLEXPORT_TEST(testTdf89165, "tdf89165.docx")
{
// This must not hang in layout
}
DECLARE_OOXMLEXPORT_TEST(testTdf95777, "tdf95777.docx")
{
// This must not fail on open
}
CPPUNIT_TEST_FIXTURE(Test, testTdf94374)
{
createSwDoc("hello.docx");
uno::Reference<text::XTextDocument> xTextDocument(mxComponent, uno::UNO_QUERY);
uno::Reference<text::XTextRange> xText = xTextDocument->getText();
uno::Reference<text::XTextRange> xEnd = xText->getEnd();
// This failed: it wasn't possible to insert a DOCX document into an existing Writer one.
paste(u"ooxmlexport/data/tdf94374.docx", "com.sun.star.comp.Writer.WriterFilter", xEnd);
}
DECLARE_OOXMLEXPORT_TEST(testTdf83300, "tdf83300.docx")
{
// tdf#143722: This was 'TOC Heading', upon updating a TOC the heading replaced its Word-default blue + Calibri style
// with a Writer-default black + Liberation Sans one
CPPUNIT_ASSERT_EQUAL(OUString("Contents Heading"),
getProperty<OUString>(getParagraph(1), "ParaStyleName"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf78902, "tdf78902.docx")
{
// This hung in layout.
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
DECLARE_OOXMLEXPORT_TEST(testTdf95775, "tdf95775.docx")
{
// This must not fail in layout
}
DECLARE_OOXMLEXPORT_TEST(testTdf92157, "tdf92157.docx")
{
// A graphic with dimensions 0,0 should not fail on load
// Additionally, the bookmark names should not change (they got a "1" appended when copied)
uno::Reference<text::XBookmarksSupplier> xBookmarksSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XNameAccess> xBookmarksByName = xBookmarksSupplier->getBookmarks();
CPPUNIT_ASSERT(xBookmarksByName->hasByName("referentiegegevens"));
CPPUNIT_ASSERT(xBookmarksByName->hasByName("referentiegegevens_bk"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf97417, "section_break_numbering.docx")
{
uno::Reference<beans::XPropertySet> xProps(getParagraph(1), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("1st page: first paragraph erroneous numbering",
!xProps->getPropertyValue("NumberingRules").hasValue());
// paragraph with numbering and section break was removed by writerfilter
// but its numbering was copied to all following paragraphs
CPPUNIT_ASSERT_MESSAGE(
"2nd page: first paragraph missing numbering",
getProperty<uno::Reference<container::XIndexAccess>>(getParagraph(2), "NumberingRules")
.is());
xProps = uno::Reference<beans::XPropertySet>(getParagraph(3), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_MESSAGE("2nd page: second paragraph erroneous numbering",
!xProps->getPropertyValue("NumberingRules").hasValue());
CPPUNIT_ASSERT_EQUAL(2, getPages());
}
DECLARE_OOXMLEXPORT_TEST(testTdf94043, "tdf94043.docx")
{
auto xTextSection
= getProperty<uno::Reference<beans::XPropertySet>>(getParagraph(2), "TextSection");
auto xTextColumns
= getProperty<uno::Reference<text::XTextColumns>>(xTextSection, "TextColumns");
// This was 0, the separator line was not visible due to 0 width.
CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(2),
getProperty<sal_Int32>(xTextColumns, "SeparatorLineWidth"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf95213, "tdf95213.docx")
{
// Get the second paragraph's numbering style's 2nd level's character style name.
uno::Reference<text::XTextRange> xParagraph = getParagraph(2);
auto xLevels
= getProperty<uno::Reference<container::XIndexAccess>>(xParagraph, "NumberingRules");
uno::Sequence<beans::PropertyValue> aLevel;
xLevels->getByIndex(1) >>= aLevel; // 2nd level
OUString aName = std::find_if(std::cbegin(aLevel), std::cend(aLevel),
[](const beans::PropertyValue& rValue) {
return rValue.Name == "CharStyleName";
})
->Value.get<OUString>();
uno::Reference<beans::XPropertySet> xStyle(getStyles("CharacterStyles")->getByName(aName),
uno::UNO_QUERY);
// This was awt::FontWeight::BOLD.
CPPUNIT_ASSERT_EQUAL(awt::FontWeight::NORMAL, getProperty<float>(xStyle, "CharWeight"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf97371, "tdf97371.docx")
{
SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
CPPUNIT_ASSERT(pTextDoc);
SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
SdrObject* pShape = pPage->GetObj(0);
SdrObject* pTextBox = pPage->GetObj(1);
tools::Long nDiff = std::abs(pShape->GetSnapRect().Top() - pTextBox->GetSnapRect().Top());
// The top of the two shapes were 410 and 3951, now it should be 3950 and 3951.
CPPUNIT_ASSERT(nDiff < 10);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf99140)
{
SwModelTestBase::FlySplitGuard aGuard;
auto verify = [this]() {
// A multi-page floating table appeared only on the first page.
SwDoc* pDoc = getSwDoc();
SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
CPPUNIT_ASSERT(pPage1);
const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
CPPUNIT_ASSERT(pPage1Fly);
SwFrame* pTab1 = pPage1Fly->GetLower();
// This was text::HoriOrientation::NONE, the second table was too wide due to this.
CPPUNIT_ASSERT_EQUAL(static_cast<tools::Long>(9622), pTab1->getFrameArea().Width());
SwFrame* pRow1 = pTab1->GetLower();
SwFrame* pCell1 = pRow1->GetLower();
auto pText1 = dynamic_cast<SwTextFrame*>(pCell1->GetLower());
CPPUNIT_ASSERT(pText1);
CPPUNIT_ASSERT_EQUAL(OUString("Table2:A1"), pText1->GetText());
auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
CPPUNIT_ASSERT(pPage2);
const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
auto pPage2Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage2Objs[0]);
CPPUNIT_ASSERT(pPage2Fly);
SwFrame* pTab2 = pPage2Fly->GetLower();
SwFrame* pRow2 = pTab2->GetLower();
SwFrame* pCell2 = pRow2->GetLower();
auto pText2 = dynamic_cast<SwTextFrame*>(pCell2->GetLower());
CPPUNIT_ASSERT(pText2);
CPPUNIT_ASSERT_EQUAL(OUString("Table2:A2"), pText2->GetText());
};
createSwDoc("tdf99140.docx");
verify();
reload(mpFilter, "tdf99140.docx");
verify();
}
CPPUNIT_TEST_FIXTURE(Test, testTableMarginAdjustment)
{
loadAndReload("table.fodt");
// Writer, (new) Word: margin 0 means table border starts at 0
// (old) Word: margin 0 means paragraph in table starts at 0
auto const xTable(getParagraphOrTable(1));
// shifted very slightly to account for half of the thin border width, so 4, not 0.
CPPUNIT_ASSERT_EQUAL(sal_Int32(4), getProperty<sal_Int32>(xTable, "LeftMargin"));
// Now that compatibilityMode is set to 2013's 15 (new), expect the new values,
// since LO is exporting in the NEW way now instead of the OLD way.
// This was 55 when using 2007's compatibilityMode of 12 (old)
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "type", "dxa");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "w", "0");
// tdf#143982: automatic tables should export as something better than just left-and-size
CPPUNIT_ASSERT_EQUAL(sal_Int16(100), getProperty<sal_Int16>(xTable, "RelativeWidth"));
}
DECLARE_OOXMLEXPORT_TEST(testTdf119760_tableInTablePosition, "tdf119760_tableInTablePosition.docx")
{
if (isExported())
{
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tr[1]/w:tc[1]/w:tbl[1]/w:tblPr[1]/w:tblInd[1]", "type",
"dxa");
assertXPath(pXmlDoc, "//w:tbl[1]/w:tr[1]/w:tc[1]/w:tbl[1]//w:tblPr[1]/w:tblInd[1]", "w",
"0");
}
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
uno::Reference<text::XTextTable> xTable(xTables->getByIndex(0), uno::UNO_QUERY);
// For compatibilityMode 15: margin 0 means table border starts at 0,
// shifted to account for half of the thick border width, so 106, not 0.
CPPUNIT_ASSERT_EQUAL(sal_Int32(106), getProperty<sal_Int32>(xTable, "LeftMargin"));
}
DECLARE_OOXMLEXPORT_TEST(testTableCellMargin, "table-cell-margin.docx")
{
sal_Int32 const cellLeftMarginFromOffice[] = { 250, 100, 0, 0 };
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
for (int i = 0; i < 4; i++)
{
uno::Reference<text::XTextTable> xTable1(xTables->getByIndex(i), uno::UNO_QUERY);
// Verify left margin of 1st cell :
// * Office left margins are measured relative to the right of the border
// * LO left spacing is measured from the center of the border
uno::Reference<table::XCell> xCell = xTable1->getCellByName("A1");
uno::Reference<beans::XPropertySet> xPropSet(xCell, uno::UNO_QUERY_THROW);
sal_Int32 aLeftMargin = -1;
xPropSet->getPropertyValue("LeftBorderDistance") >>= aLeftMargin;
uno::Any aLeftBorder = xPropSet->getPropertyValue("LeftBorder");
table::BorderLine2 aLeftBorderLine;
aLeftBorder >>= aLeftBorderLine;
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE(
"Incorrect left spacing computed from docx cell margin", cellLeftMarginFromOffice[i],
aLeftMargin - 0.5 * aLeftBorderLine.LineWidth, 1);
// The 'a' in the fourth table should not be partly hidden by the border
if (i == 3)
{
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect cell left padding",
0.5 * aLeftBorderLine.LineWidth, aLeftMargin, 1);
// tdf#119885: cell's edit area must touch right border
sal_Int32 aRightMargin = -1;
xPropSet->getPropertyValue("RightBorderDistance") >>= aRightMargin;
uno::Any aRightBorder = xPropSet->getPropertyValue("RightBorder");
table::BorderLine2 aRightBorderLine;
aRightBorder >>= aRightBorderLine;
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect cell right padding",
0.5 * aRightBorderLine.LineWidth, aRightMargin, 1);
}
}
}
CPPUNIT_TEST_FIXTURE(Test, TestPuzzleExport)
{
loadAndReload("TestPuzzleExport.odt");
// See tdf#148342 for details
// Get the doc
uno::Reference<text::XTextDocument> xTextDoc(mxComponent, uno::UNO_QUERY_THROW);
auto pSwDoc = dynamic_cast<SwXTextDocument*>(xTextDoc.get());
CPPUNIT_ASSERT(pSwDoc);
// Create a metafile
auto pMeta = pSwDoc->GetDocShell()->GetPreviewMetaFile();
CPPUNIT_ASSERT(pMeta);
MetafileXmlDump aDumper;
auto pMetaXml = dumpAndParse(aDumper, *pMeta);
CPPUNIT_ASSERT(pMetaXml);
// After parsing check that node...
auto pXNode
= getXPathNode(pMetaXml, "/metafile/push/push/push/push[4]/push/push/polypolygon/polygon");
CPPUNIT_ASSERT(pXNode);
auto pNode = pXNode->nodesetval->nodeTab[0];
CPPUNIT_ASSERT(pNode);
auto it = pNode->children;
int nCount = 0;
// .. and count the children
while (it != nullptr)
{
nCount++;
it = it->next;
}
// In case of puzzle there will be so many... Without the fix there was a rectangle with 4 points.
CPPUNIT_ASSERT_GREATER(300, nCount);
}
// tdf#106742 for DOCX with compatibility level <= 14 (MS Word up to and incl. ver.2010), we should use cell margins when calculating table left border position
DECLARE_OOXMLEXPORT_TEST(testTablePosition14, "table-position-14.docx")
{
sal_Int32 const aXCoordsFromOffice[] = { 2500, -1000, 0, 0 };
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
for (int i = 0; i < 4; i++)
{
uno::Reference<text::XTextTable> xTable1(xTables->getByIndex(i), uno::UNO_QUERY);
// Verify X coord
uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(),
uno::UNO_QUERY);
xCtrl->select(uno::Any(xTable1));
uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl,
uno::UNO_QUERY);
uno::Reference<text::XTextViewCursor> xCursor = xTextViewCursorSupplier->getViewCursor();
awt::Point pos = xCursor->getPosition();
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect X coord computed from docx",
aXCoordsFromOffice[i], pos.X, 1);
}
}
// tdf#106742 for DOCX with compatibility level > 14 (MS Word since ver.2013),
// we should NOT use cell margins when calculating table left border position. But we do need to use border width.
DECLARE_OOXMLEXPORT_TEST(testTablePosition15, "table-position-15.docx")
{
sal_Int32 const aXCoordsFromOffice[] = { 2751, -899, 1, 212 };
uno::Reference<text::XTextTablesSupplier> xTablesSupplier(mxComponent, uno::UNO_QUERY);
uno::Reference<frame::XModel> xModel(mxComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xTables(xTablesSupplier->getTextTables(),
uno::UNO_QUERY);
for (int i = 0; i < 4; i++)
{
uno::Reference<text::XTextTable> xTable1(xTables->getByIndex(i), uno::UNO_QUERY);
// Verify X coord
uno::Reference<view::XSelectionSupplier> xCtrl(xModel->getCurrentController(),
uno::UNO_QUERY);
xCtrl->select(uno::Any(xTable1));
uno::Reference<text::XTextViewCursorSupplier> xTextViewCursorSupplier(xCtrl,
uno::UNO_QUERY);
uno::Reference<text::XTextViewCursor> xCursor = xTextViewCursorSupplier->getViewCursor();
awt::Point pos = xCursor->getPosition();
CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("Incorrect X coord computed from docx",
aXCoordsFromOffice[i], pos.X, 1);
}
}
DECLARE_OOXMLEXPORT_TEST(testTdf107359, "tdf107359-char-pitch.docx")
{
uno::Reference<beans::XPropertySet> xPropertySet(getStyles("PageStyles")->getByName("Standard"),
uno::UNO_QUERY);
bool bGridSnapToChars;
xPropertySet->getPropertyValue("GridSnapToChars") >>= bGridSnapToChars;
CPPUNIT_ASSERT_EQUAL(false, bGridSnapToChars);
sal_Int32 nRubyHeight;
xPropertySet->getPropertyValue("GridRubyHeight") >>= nRubyHeight;
CPPUNIT_ASSERT_EQUAL(sal_Int32(0), nRubyHeight);
sal_Int32 nBaseHeight;
xPropertySet->getPropertyValue("GridBaseHeight") >>= nBaseHeight;
CPPUNIT_ASSERT_EQUAL(sal_Int32(convertTwipToMm100(18 * 20)), nBaseHeight);
sal_Int32 nBaseWidth;
xPropertySet->getPropertyValue("GridBaseWidth") >>= nBaseWidth;
CPPUNIT_ASSERT_EQUAL(sal_Int32(convertTwipToMm100(24 * 20)), nBaseWidth);
}
CPPUNIT_TEST_FIXTURE(Test, testTdf77236_MissingSolidFill)
{
loadAndSave("tdf77236_MissingSolidFill.docx");
// tdf#77236: solidFill of VML shape was not exported if the colors of line and style were the same
xmlDocUniquePtr pXmlDoc = parseExport("word/document.xml");
assertXPath(
pXmlDoc,
"//mc:Choice/w:drawing/wp:inline/a:graphic/a:graphicData/wps:wsp/wps:spPr/a:ln/a:solidFill",
1);
}
DECLARE_OOXMLEXPORT_TEST(testTdf105875_VmlShapeRotationWithFlip,
"tdf105875_VmlShapeRotationWithFlip.docx")
{
// tdf#105875: check whether the rotation of the VML bezier shape is ok (with flip too)
// TODO: fix export too
if (isExported())
return;
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(1), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_EQUAL(sal_Int32(0),
xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>());
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(2), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(220 * 100),
xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(),
1);
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(3), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(320 * 100),
xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(),
1);
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(4), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(140 * 100),
xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(),
1);
}
{
uno::Reference<beans::XPropertySet> xPropertySet(getShape(5), uno::UNO_QUERY_THROW);
CPPUNIT_ASSERT_DOUBLES_EQUAL(
sal_Int32(40 * 100), xPropertySet->getPropertyValue("RotateAngle").get<sal_Int32>(), 1);
}
}
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */