MM: first unit test and infrastructure

Extendes SwModelTestBase with mail merge functions and a declaration
of the DECLARE_MAILMERGE_TEST macro and uses it in a first test.
As most tests it's registered as a slow test run by 'make check'.

The broken MM used to drop the leading empty pages, which resulted
in a document with 4 pages and the two page bound draws merged
per single page.

Tests the MM result for page count (eight) and each draw anchor to
be on a different page.

Change-Id: Iab17f5844e68221d48cb89863323bcfe4c8ae0d2
This commit is contained in:
Jan-Marek Glogowski 2014-09-23 10:00:13 +02:00
parent 5187ce45b9
commit d10f6d49b7
6 changed files with 329 additions and 2 deletions

View file

@ -0,0 +1,93 @@
# -*- 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 gb_CppunitTest_CppunitTest,sw_mailmerge))
$(eval $(call gb_CppunitTest_add_exception_objects,sw_mailmerge, \
sw/qa/extras/mailmerge/mailmerge \
))
$(eval $(call gb_CppunitTest_use_libraries,sw_mailmerge, \
comphelper \
cppu \
sal \
sw \
test \
unotest \
utl \
))
$(eval $(call gb_CppunitTest_use_externals,sw_mailmerge, \
boost_headers \
libxml2 \
))
$(eval $(call gb_CppunitTest_use_api,sw_mailmerge,\
offapi \
udkapi \
))
$(eval $(call gb_CppunitTest_use_components,sw_mailmerge, \
basic/util/sb \
comphelper/util/comphelp \
configmgr/source/configmgr \
connectivity/source/cpool/dbpool2 \
connectivity/source/drivers/calc/calc \
connectivity/source/manager/sdbc2 \
dbaccess/source/filter/xml/dbaxml \
dbaccess/util/dba \
embeddedobj/util/embobj \
filter/source/config/cache/filterconfig1 \
filter/source/storagefilterdetect/storagefd \
forms/util/frm \
framework/util/fwk \
i18npool/util/i18npool \
lingucomponent/source/languageguessing/guesslang \
linguistic/source/lng \
oox/util/oox \
package/source/xstor/xstor \
package/util/package2 \
sax/source/expatwrap/expwrap \
sc/util/sc \
sfx2/util/sfx \
sot/util/sot \
svl/source/fsstor/fsstorage \
svl/util/svl \
svtools/util/svt \
sw/util/sw \
sw/util/swd \
toolkit/util/tk \
ucb/source/core/ucb1 \
ucb/source/ucp/file/ucpfile1 \
ucb/source/ucp/tdoc/ucptdoc1 \
unotools/util/utl \
unoxml/source/rdf/unordf \
unoxml/source/service/unoxml \
uui/util/uui \
$(if $(filter-out MACOSX WNT,$(OS)), \
$(if $(ENABLE_HEADLESS),, \
vcl/vcl.unx \
) \
) \
xmloff/util/xo \
))
$(eval $(call gb_CppunitTest_use_configuration,sw_mailmerge))
$(eval $(call gb_CppunitTest_use_ure,sw_mailmerge))
$(eval $(call gb_CppunitTest_use_vcl,sw_mailmerge))
$(eval $(call gb_CppunitTest_set_include,sw_mailmerge,\
-I$(SRCDIR)/sw/inc \
-I$(SRCDIR)/sw/source/core/inc \
-I$(SRCDIR)/sw/qa/extras/inc \
-I$(SRCDIR)/sw/source/uibase/inc \
$$(INCLUDE) \
))
# vim: set noet sw=4 ts=4:

View file

@ -71,6 +71,7 @@ $(eval $(call gb_Module_add_slowcheck_targets,sw,\
CppunitTest_sw_odfexport \
CppunitTest_sw_odfimport \
CppunitTest_sw_uiwriter \
CppunitTest_sw_mailmerge \
))
ifneq ($(DISABLE_CVE_TESTS),TRUE)

View file

@ -23,6 +23,11 @@
#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
#include <com/sun/star/table/XCell.hpp>
#include <com/sun/star/table/BorderLine2.hpp>
#include <com/sun/star/task/XJob.hpp>
#include <com/sun/star/sdb/CommandType.hpp>
#include <com/sun/star/sdb/DatabaseContext.hpp>
#include <com/sun/star/sdb/XDocumentDataSource.hpp>
#include <com/sun/star/text/MailMergeType.hpp>
#include <test/bootstrapfixture.hxx>
#include <test/xmltesttools.hxx>
@ -34,6 +39,8 @@
#include <comphelper/processfactory.hxx>
#include <unotools/tempfile.hxx>
#include <unotools/mediadescriptor.hxx>
#include <dbmgr.hxx>
#include <unoprnms.hxx>
#include <unotxdoc.hxx>
#include <docsh.hxx>
@ -135,6 +142,29 @@ using namespace css;
CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
void TestName::verify()
#define DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, BaseClass) \
class TestName : public BaseClass { \
protected: \
virtual OUString getTestName() SAL_OVERRIDE { return OUString::createFromAscii(#TestName); } \
public: \
CPPUNIT_TEST_SUITE(TestName); \
CPPUNIT_TEST(MailMerge); \
CPPUNIT_TEST_SUITE_END(); \
\
void MailMerge() { \
executeMailMergeTest(filename, datasource, tablename); \
} \
void verify() SAL_OVERRIDE; \
}; \
CPPUNIT_TEST_SUITE_REGISTRATION(TestName); \
void TestName::verify()
/**
* Maps database URIs to the registered database names for quick lookups
*/
typedef std::map<OUString, OUString> DBuriMap;
DBuriMap aDBuriMap;
/// Base class for filter tests loading or roundtriping a document, then asserting the document model.
class SwModelTestBase : public test::BootstrapFixture, public unotest::MacrosTest, public XmlTestTools
{
@ -142,7 +172,11 @@ private:
OUString maFilterOptions;
protected:
uno::Reference<lang::XComponent> mxComponent;
uno::Reference< lang::XComponent > mxComponent;
uno::Reference< lang::XComponent > mxMMComponent;
uno::Reference< com::sun::star::task::XJob > mxJob;
uno::Sequence< beans::NamedValue > mSeqMailMergeArgs;
xmlBufferPtr mpXmlBuffer;
const char* mpTestDocumentPath;
const char* mpFilter;
@ -156,7 +190,9 @@ protected:
sal_uInt32 mnStartTime;
utl::TempFile maTempFile;
utl::TempFile maTempDir;
bool mbExported; ///< Does maTempFile already contain something useful?
sal_Int16 nCurOutputType;
protected:
virtual OUString getTestName() { return OUString(); }
@ -176,7 +212,9 @@ public:
, mpTestDocumentPath(pTestDocumentPath)
, mpFilter(pFilter)
, mnStartTime(0)
, maTempDir(NULL, true)
, mbExported(false)
, nCurOutputType(0)
{
maTempFile.EnableKillingFile();
}
@ -195,6 +233,16 @@ public:
{
if (mxComponent.is())
mxComponent->dispose();
if (mxMMComponent.is())
{
if (nCurOutputType == text::MailMergeType::SHELL)
{
SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
pTxtDoc->GetDocShell()->DoClose();
}
else
mxMMComponent->dispose();
}
test::BootstrapFixture::tearDown();
}
@ -258,6 +306,32 @@ protected:
maTempFile.EnableKillingFile();
}
/**
* Helper func used by each unit test to test the 'mail merge' code.
*
* Registers the data source, loads the original file as reference,
* initializes the mail merge job and its default argument sequence.
*
* The 'verify' method actually has to execute the mail merge by
* calling executeMailMerge() after modifying the job arguments.
*/
void executeMailMergeTest(const char* filename, const char* datasource, const char* tablename = 0)
{
header();
preTest(filename);
load(mpTestDocumentPath, filename);
const OUString aPrefix( "LOMM_" );
const OUString aWorkDir = maTempDir.GetURL();
const OUString aURI( getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(datasource) );
OUString aDBName = registerDBsource( aURI, aPrefix, aWorkDir );
initMailMergeJobAndArgs( filename, tablename, aDBName, aPrefix, aWorkDir );
postTest(filename);
verify();
finish();
}
/**
* Function overloaded by unit test. See DECLARE_SW_*_TEST macros
*/
@ -288,7 +362,7 @@ protected:
}
/**
* Override this function if not calcing layout is needed
* Override this function if calcing layout is not needed
*/
virtual bool mustCalcLayoutOf(const char* /*filename*/)
{
@ -688,6 +762,89 @@ protected:
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("o"), BAD_CAST("urn:schemas-microsoft-com:office:office"));
}
virtual OUString registerDBsource( const OUString &aURI, const OUString &aPrefix, const OUString &aWorkDir )
{
OUString aDBName;
DBuriMap::const_iterator pos = aDBuriMap.find( aURI );
if (pos == aDBuriMap.end())
{
aDBName = SwDBManager::LoadAndRegisterDataSource( aURI, &aPrefix, &aWorkDir );
aDBuriMap.insert( std::pair< OUString, OUString >( aURI, aDBName ) );
std::cout << "New datasource name: '" << aDBName << "'" << std::endl;
}
else
{
aDBName = pos->second;
std::cout << "Old datasource name: '" << aDBName << "'" << std::endl;
}
CPPUNIT_ASSERT(!aDBName.isEmpty());
return aDBName;
}
virtual void initMailMergeJobAndArgs( const char* filename, const char* tablename, const OUString &aDBName,
const OUString &aPrefix, const OUString &aWorkDir )
{
uno::Reference< task::XJob > xJob( getMultiServiceFactory()->createInstance( "com.sun.star.text.MailMerge" ), uno::UNO_QUERY_THROW );
mxJob.set( xJob );
int seq_id = 5;
if (tablename) seq_id += 2;
mSeqMailMergeArgs.realloc( seq_id );
seq_id = 0;
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_TYPE ), uno::Any( text::MailMergeType::SHELL ) );
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DOCUMENT_URL ), uno::Any(
( OUString(getURLFromSrc(mpTestDocumentPath) + OUString::createFromAscii(filename)) ) ) );
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DATA_SOURCE_NAME ), uno::Any( aDBName ) );
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_OUTPUT_URL ), uno::Any( aWorkDir ) );
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_FILE_NAME_PREFIX ), uno::Any( aPrefix ));
if (tablename)
{
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND_TYPE ), uno::Any( sdb::CommandType::TABLE ) );
mSeqMailMergeArgs[ seq_id++ ] = beans::NamedValue( OUString( UNO_NAME_DAD_COMMAND ), uno::Any( OUString::createFromAscii(tablename) ) );
}
}
virtual void executeMailMerge()
{
uno::Any res = mxJob->execute( mSeqMailMergeArgs );
OUString aCurOutputURL;
OUString aCurFileNamePrefix;
const beans::NamedValue *pArguments = mSeqMailMergeArgs.getConstArray();
bool bOk = true;
sal_Int32 nArgs = mSeqMailMergeArgs.getLength();
for (sal_Int32 i = 0; i < nArgs; ++i) {
const OUString &rName = pArguments[i].Name;
const uno::Any &rValue = pArguments[i].Value;
// all error checking was already done by the MM job execution
if (rName == UNO_NAME_OUTPUT_URL)
bOk &= rValue >>= aCurOutputURL;
else if (rName == UNO_NAME_FILE_NAME_PREFIX)
bOk &= rValue >>= aCurFileNamePrefix;
else if (rName == UNO_NAME_OUTPUT_TYPE)
bOk &= rValue >>= nCurOutputType;
}
CPPUNIT_ASSERT(bOk);
if (nCurOutputType == text::MailMergeType::SHELL)
{
CPPUNIT_ASSERT(res >>= mxMMComponent);
CPPUNIT_ASSERT(mxMMComponent.is());
}
else
{
CPPUNIT_ASSERT(res == true);
mxMMComponent = loadFromDesktop( aCurOutputURL + "/" + aCurFileNamePrefix + "0.odt",
"com.sun.star.text.TextDocument");
CPPUNIT_ASSERT(mxMMComponent.is());
calcLayout();
}
}
};
/**

Binary file not shown.

View file

@ -0,0 +1,76 @@
/*
* 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>
#if !defined(MACOSX) && !defined(WNT)
#include <com/sun/star/awt/FontWeight.hpp>
#include <com/sun/star/style/PageStyleLayout.hpp>
#include <com/sun/star/table/XCell.hpp>
#include <com/sun/star/table/BorderLine.hpp>
#include <com/sun/star/text/XTextTable.hpp>
#include <com/sun/star/text/MailMergeType.hpp>
#include <com/sun/star/sdb/XDocumentDataSource.hpp>
#include <com/sun/star/text/TextContentAnchorType.hpp>
#include <wrtsh.hxx>
#include <ndtxt.hxx>
#include <swdtflvr.hxx>
#include <view.hxx>
#include <edtwin.hxx>
#include <olmenu.hxx>
#include <cmdid.h>
class MMTest : public SwModelTestBase
{
public:
MMTest() : SwModelTestBase("/sw/qa/extras/mailmerge/data/", "writer8") {}
};
#define DECLARE_DFLT_MAILMERGE_TEST(TestName, filename, datasource, tablename) \
DECLARE_MAILMERGE_TEST(TestName, filename, datasource, tablename, MMTest)
DECLARE_DFLT_MAILMERGE_TEST(testMultiPageAnchoredDraws, "multiple-page-anchored-draws.odt", "4_v01.ods", "Tabelle1")
{
executeMailMerge();
SwXTextDocument* pTxtDoc = dynamic_cast<SwXTextDocument *>(mxMMComponent.get());
CPPUNIT_ASSERT(pTxtDoc);
sal_uInt16 nPhysPages = pTxtDoc->GetDocShell()->GetWrtShell()->GetPhyPageNum();
CPPUNIT_ASSERT_EQUAL(sal_uInt16(8), nPhysPages);
uno::Reference<drawing::XDrawPageSupplier> xDrawPageSupplier(mxMMComponent, uno::UNO_QUERY);
uno::Reference<container::XIndexAccess> xDraws(xDrawPageSupplier->getDrawPage(), uno::UNO_QUERY);
CPPUNIT_ASSERT_EQUAL(sal_Int32(8), xDraws->getCount());
// bitset of all page numbers
char nPageSum = 0xFF;
uno::Reference<beans::XPropertySet> xPropertySet;
for (sal_Int32 i = 0; i < xDraws->getCount(); i++)
{
text::TextContentAnchorType nAnchorType;
sal_uInt16 nAnchorPageNo;
xPropertySet.set(xDraws->getByIndex(i), uno::UNO_QUERY);
xPropertySet->getPropertyValue( UNO_NAME_ANCHOR_TYPE ) >>= nAnchorType;
CPPUNIT_ASSERT_EQUAL( text::TextContentAnchorType_AT_PAGE, nAnchorType );
xPropertySet->getPropertyValue( UNO_NAME_ANCHOR_PAGE_NO ) >>= nAnchorPageNo;
nPageSum &= !nAnchorPageNo;
}
// are all shapes are on different page numbers?
CPPUNIT_ASSERT_EQUAL(char(0), nPageSum);
}
#endif
CPPUNIT_PLUGIN_IMPLEMENT();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */