1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
10 #include <sal/config.h>
11 #include <unotest/filters-test.hxx>
12 #include <test/bootstrapfixture.hxx>
13 #include <rtl/strbuf.hxx>
14 #include <osl/file.hxx>
16 #include <sfx2/app.hxx>
17 #include <sfx2/docfilt.hxx>
18 #include <sfx2/docfile.hxx>
19 #include <sfx2/frame.hxx>
20 #include <sfx2/sfxmodelfactory.hxx>
21 #include <svl/stritem.hxx>
23 #include <unotools/tempfile.hxx>
24 #include <comphelper/storagehelper.hxx>
26 #define CALC_DEBUG_OUTPUT 0
27 #define TEST_BUG_FILES 0
29 #include "helper/qahelper.hxx"
33 #include "patattr.hxx"
34 #include "scitems.hxx"
35 #include "document.hxx"
36 #include "cellform.hxx"
38 #define ODS_FORMAT_TYPE 50331943
39 #define XLS_FORMAT_TYPE 318767171
40 #define XLSX_FORMAT_TYPE 268959811
41 #define LOTUS123_FORMAT_TYPE 268435649
48 using namespace ::com::sun::star
;
49 using namespace ::com::sun::star::uno
;
54 const char* pName
; const char* pFilterName
; const char* pTypeName
; unsigned int nFormatType
;
57 FileFormat aFileFormats
[] = {
58 { "ods" , "calc8", "", ODS_FORMAT_TYPE
},
59 { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE
},
60 { "xlsx", "Calc MS Excel 2007 XML" , "MS Excel 2007 XML", XLSX_FORMAT_TYPE
},
61 { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE
}
66 class ScExportTest
: public test::BootstrapFixture
72 virtual void tearDown();
74 ScDocShellRef
saveAndReload( ScDocShell
*, const rtl::OUString
&, const rtl::OUString
&, const rtl::OUString
&, sal_uLong
);
75 ScDocShellRef
saveAndReloadPassword( ScDocShell
*, const rtl::OUString
&, const rtl::OUString
&, const rtl::OUString
&, sal_uLong
);
78 void testPasswordExport();
79 void testConditionalFormatExportXLSX();
80 void testMiscRowHeightExport();
82 CPPUNIT_TEST_SUITE(ScExportTest
);
84 #if !defined(MACOSX) && !defined(DRAGONFLY) && !defined(WNT)
85 CPPUNIT_TEST(testPasswordExport
);
87 CPPUNIT_TEST(testConditionalFormatExportXLSX
);
88 CPPUNIT_TEST(testMiscRowHeightExport
);
89 CPPUNIT_TEST_SUITE_END();
92 rtl::OUString m_aBaseString
;
93 uno::Reference
<uno::XInterface
> m_xCalcComponent
;
96 const OUString
& rURL
, const OUString
& rFilter
, const OUString
&rUserData
,
97 const OUString
& rTypeName
, sal_Int32 nFormat
, sal_uLong nFormatType
,
98 const OUString
* pPassword
= NULL
);
100 ScDocShellRef
saveAndReload( ScDocShell
* pShell
, sal_Int32 nFormat
);
101 ScDocShellRef
loadDocument( const rtl::OUString
& rFileNameBase
, sal_Int32 nFormat
);
102 void createFileURL( const rtl::OUString
& aFileBase
, const rtl::OUString
& rFileExtension
, rtl::OUString
& rFilePath
);
103 void createCSVPath(const rtl::OUString
& rFileBase
, rtl::OUString
& rCSVPath
);
106 void ScExportTest::createFileURL(const rtl::OUString
& aFileBase
, const rtl::OUString
& aFileExtension
, rtl::OUString
& rFilePath
)
108 rtl::OUString
aSep("/");
109 rtl::OUStringBuffer
aBuffer( getSrcRootURL() );
110 aBuffer
.append(m_aBaseString
).append(aSep
).append(aFileExtension
);
111 aBuffer
.append(aSep
).append(aFileBase
).append(aFileExtension
);
112 rFilePath
= aBuffer
.makeStringAndClear();
115 void ScExportTest::createCSVPath(const rtl::OUString
& aFileBase
, rtl::OUString
& rCSVPath
)
117 rtl::OUStringBuffer
aBuffer(getSrcRootPath());
118 aBuffer
.append(m_aBaseString
).append(rtl::OUString("/contentCSV/"));
119 aBuffer
.append(aFileBase
).append(rtl::OUString("csv"));
120 rCSVPath
= aBuffer
.makeStringAndClear();
123 ScDocShellRef
ScExportTest::saveAndReloadPassword(ScDocShell
* pShell
, const rtl::OUString
&rFilter
,
124 const rtl::OUString
&rUserData
, const rtl::OUString
& rTypeName
, sal_uLong nFormatType
)
126 utl::TempFile aTempFile
;
127 aTempFile
.EnableKillingFile();
128 SfxMedium
aStoreMedium( aTempFile
.GetURL(), STREAM_STD_WRITE
);
129 sal_uInt32 nExportFormat
= 0;
130 if (nFormatType
== ODS_FORMAT_TYPE
)
131 nExportFormat
= SFX_FILTER_EXPORT
| SFX_FILTER_USESOPTIONS
;
132 SfxFilter
* pExportFilter
= new SfxFilter(
134 rtl::OUString(), nFormatType
, nExportFormat
, rTypeName
, 0, rtl::OUString(),
135 rUserData
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
136 pExportFilter
->SetVersion(SOFFICE_FILEFORMAT_CURRENT
);
137 aStoreMedium
.SetFilter(pExportFilter
);
138 SfxItemSet
* pExportSet
= aStoreMedium
.GetItemSet();
139 uno::Sequence
< beans::NamedValue
> aEncryptionData
= comphelper::OStorageHelper::CreatePackageEncryptionData( rtl::OUString("test") );
140 uno::Any xEncryptionData
;
141 xEncryptionData
<<= aEncryptionData
;
142 pExportSet
->Put(SfxUnoAnyItem(SID_ENCRYPTIONDATA
, xEncryptionData
));
144 uno::Reference
< embed::XStorage
> xMedStorage
= aStoreMedium
.GetStorage();
145 ::comphelper::OStorageHelper::SetCommonStorageEncryptionData( xMedStorage
, aEncryptionData
);
147 pShell
->DoSaveAs( aStoreMedium
);
150 //std::cout << "File: " << aTempFile.GetURL() << std::endl;
152 sal_uInt32 nFormat
= 0;
153 if (nFormatType
== ODS_FORMAT_TYPE
)
154 nFormat
= SFX_FILTER_IMPORT
| SFX_FILTER_USESOPTIONS
;
156 OUString
aPass("test");
157 return load(aTempFile
.GetURL(), rFilter
, rUserData
, rTypeName
, nFormat
, nFormatType
, &aPass
);
160 ScDocShellRef
ScExportTest::saveAndReload(ScDocShell
* pShell
, const rtl::OUString
&rFilter
,
161 const rtl::OUString
&rUserData
, const rtl::OUString
& rTypeName
, sal_uLong nFormatType
)
164 utl::TempFile aTempFile
;
165 aTempFile
.EnableKillingFile();
166 SfxMedium
aStoreMedium( aTempFile
.GetURL(), STREAM_STD_WRITE
);
167 sal_uInt32 nExportFormat
= 0;
168 if (nFormatType
== ODS_FORMAT_TYPE
)
169 nExportFormat
= SFX_FILTER_EXPORT
| SFX_FILTER_USESOPTIONS
;
170 SfxFilter
* pExportFilter
= new SfxFilter(
172 rtl::OUString(), nFormatType
, nExportFormat
, rTypeName
, 0, rtl::OUString(),
173 rUserData
, rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("private:factory/scalc*")) );
174 pExportFilter
->SetVersion(SOFFICE_FILEFORMAT_CURRENT
);
175 aStoreMedium
.SetFilter(pExportFilter
);
176 pShell
->DoSaveAs( aStoreMedium
);
179 //std::cout << "File: " << aTempFile.GetURL() << std::endl;
181 sal_uInt32 nFormat
= 0;
182 if (nFormatType
== ODS_FORMAT_TYPE
)
183 nFormat
= SFX_FILTER_IMPORT
| SFX_FILTER_USESOPTIONS
;
185 return load(aTempFile
.GetURL(), rFilter
, rUserData
, rTypeName
, nFormat
, nFormatType
);
188 ScDocShellRef
ScExportTest::load(
189 const OUString
& rURL
, const OUString
& rFilter
, const OUString
&rUserData
,
190 const OUString
& rTypeName
, sal_Int32 nFormat
, sal_uLong nFormatType
, const OUString
* pPassword
)
192 SfxFilter
* pFilter
= new SfxFilter(
194 rtl::OUString(), nFormatType
, nFormat
, rTypeName
, 0, rtl::OUString(),
195 rUserData
, OUString("private:factory/scalc*"));
196 pFilter
->SetVersion(SOFFICE_FILEFORMAT_CURRENT
);
198 ScDocShellRef xDocShRef
= new ScDocShell
;
199 xDocShRef
->GetDocument()->EnableUserInteraction(false);
200 SfxMedium
* pSrcMed
= new SfxMedium(rURL
, STREAM_STD_READ
);
201 pSrcMed
->SetFilter(pFilter
);
202 pSrcMed
->UseInteractionHandler(false);
205 SfxItemSet
* pSet
= pSrcMed
->GetItemSet();
206 pSet
->Put(SfxStringItem(SID_PASSWORD
, *pPassword
));
208 if (!xDocShRef
->DoLoad(pSrcMed
))
210 xDocShRef
->DoClose();
218 ScDocShellRef
ScExportTest::saveAndReload( ScDocShell
* pShell
, sal_Int32 nFormat
)
220 rtl::OUString
aFileExtension(aFileFormats
[nFormat
].pName
, strlen(aFileFormats
[nFormat
].pName
), RTL_TEXTENCODING_UTF8
);
221 rtl::OUString
aFilterName(aFileFormats
[nFormat
].pFilterName
, strlen(aFileFormats
[nFormat
].pFilterName
), RTL_TEXTENCODING_UTF8
) ;
222 rtl::OUString
aFilterType(aFileFormats
[nFormat
].pTypeName
, strlen(aFileFormats
[nFormat
].pTypeName
), RTL_TEXTENCODING_UTF8
);
223 ScDocShellRef xDocSh
= saveAndReload(pShell
, aFilterName
, rtl::OUString(), aFilterType
, aFileFormats
[nFormat
].nFormatType
);
225 CPPUNIT_ASSERT(xDocSh
.Is());
229 ScDocShellRef
ScExportTest::loadDocument(const rtl::OUString
& rFileName
, sal_Int32 nFormat
)
231 rtl::OUString
aFileExtension(aFileFormats
[nFormat
].pName
, strlen(aFileFormats
[nFormat
].pName
), RTL_TEXTENCODING_UTF8
);
232 rtl::OUString
aFilterName(aFileFormats
[nFormat
].pFilterName
, strlen(aFileFormats
[nFormat
].pFilterName
), RTL_TEXTENCODING_UTF8
) ;
233 rtl::OUString aFileName
;
234 createFileURL( rFileName
, aFileExtension
, aFileName
);
235 rtl::OUString
aFilterType(aFileFormats
[nFormat
].pTypeName
, strlen(aFileFormats
[nFormat
].pTypeName
), RTL_TEXTENCODING_UTF8
);
236 unsigned int nFormatType
= aFileFormats
[nFormat
].nFormatType
;
237 unsigned int nClipboardId
= nFormatType
? SFX_FILTER_IMPORT
| SFX_FILTER_USESOPTIONS
: 0;
239 return load(aFileName
, aFilterName
, OUString(), aFilterType
, nClipboardId
, nFormatType
);
242 void ScExportTest::test()
244 ScDocShell
* pShell
= new ScDocShell(
246 SFXMODEL_DISABLE_EMBEDDED_SCRIPTS
|
247 SFXMODEL_DISABLE_DOCUMENT_RECOVERY
);
250 ScDocument
* pDoc
= pShell
->GetDocument();
252 pDoc
->SetValue(0,0,0, 1.0);
253 CPPUNIT_ASSERT(pDoc
);
255 ScDocShellRef xDocSh
= saveAndReload( pShell
, ODS
);
257 CPPUNIT_ASSERT(xDocSh
.Is());
258 ScDocument
* pLoadedDoc
= xDocSh
->GetDocument();
259 double aVal
= pLoadedDoc
->GetValue(0,0,0);
260 CPPUNIT_ASSERT_DOUBLES_EQUAL(aVal
, 1.0, 1e-8);
263 void ScExportTest::testPasswordExport()
265 ScDocShell
* pShell
= new ScDocShell(
267 SFXMODEL_DISABLE_EMBEDDED_SCRIPTS
|
268 SFXMODEL_DISABLE_DOCUMENT_RECOVERY
);
271 ScDocument
* pDoc
= pShell
->GetDocument();
273 pDoc
->SetValue(0,0,0, 1.0);
274 CPPUNIT_ASSERT(pDoc
);
276 sal_Int32 nFormat
= ODS
;
277 rtl::OUString
aFileExtension(aFileFormats
[nFormat
].pName
, strlen(aFileFormats
[nFormat
].pName
), RTL_TEXTENCODING_UTF8
);
278 rtl::OUString
aFilterName(aFileFormats
[nFormat
].pFilterName
, strlen(aFileFormats
[nFormat
].pFilterName
), RTL_TEXTENCODING_UTF8
) ;
279 rtl::OUString
aFilterType(aFileFormats
[nFormat
].pTypeName
, strlen(aFileFormats
[nFormat
].pTypeName
), RTL_TEXTENCODING_UTF8
);
280 ScDocShellRef xDocSh
= saveAndReloadPassword(pShell
, aFilterName
, rtl::OUString(), aFilterType
, aFileFormats
[nFormat
].nFormatType
);
282 CPPUNIT_ASSERT(xDocSh
.Is());
283 ScDocument
* pLoadedDoc
= xDocSh
->GetDocument();
284 double aVal
= pLoadedDoc
->GetValue(0,0,0);
285 CPPUNIT_ASSERT_DOUBLES_EQUAL(aVal
, 1.0, 1e-8);
288 void ScExportTest::testConditionalFormatExportXLSX()
290 ScDocShellRef xShell
= loadDocument("new_cond_format_test.", XLSX
);
291 CPPUNIT_ASSERT(xShell
.Is());
293 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), XLSX
);
294 CPPUNIT_ASSERT(xDocSh
.Is());
295 ScDocument
* pDoc
= xDocSh
->GetDocument();
296 rtl::OUString
aCSVFile("new_cond_format_test.");
297 rtl::OUString aCSVPath
;
298 createCSVPath( aCSVFile
, aCSVPath
);
299 testCondFile(aCSVPath
, pDoc
, 0);
302 void ScExportTest::testMiscRowHeightExport()
314 const char* sTestDoc
;
321 TestParam::RowData DfltRowData
[] =
326 { 1048573, 1048575, 0, 529 },
329 TestParam::RowData EmptyRepeatRowData
[] =
336 TestParam aTestValues
[] =
338 { "miscrowheights.", XLSX
, XLSX
, SAL_N_ELEMENTS(DfltRowData
), DfltRowData
},
339 { "miscrowheights.", XLSX
, XLS
, SAL_N_ELEMENTS(DfltRowData
), DfltRowData
},
340 { "miscemptyrepeatedrowheights.", ODS
, XLSX
, SAL_N_ELEMENTS(EmptyRepeatRowData
), EmptyRepeatRowData
},
341 { "miscemptyrepeatedrowheights.", ODS
, XLS
, SAL_N_ELEMENTS(EmptyRepeatRowData
), EmptyRepeatRowData
},
344 for ( unsigned int index
=0; index
<SAL_N_ELEMENTS(aTestValues
); ++index
)
346 OUString sFileName
= OUString::createFromAscii( aTestValues
[ index
].sTestDoc
);
347 printf("aTestValues[%d] %s\n", index
, OUStringToOString( sFileName
, RTL_TEXTENCODING_UTF8
).getStr() );
348 int nImportType
= aTestValues
[ index
].nImportType
;
349 int nExportType
= aTestValues
[ index
].nExportType
;
350 ScDocShellRef xShell
= loadDocument( sFileName
, nImportType
);
351 CPPUNIT_ASSERT(xShell
.Is());
353 ScDocShellRef xDocSh
= saveAndReload(&(*xShell
), nExportType
);
354 CPPUNIT_ASSERT(xDocSh
.Is());
356 ScDocument
* pDoc
= xDocSh
->GetDocument();
358 for (int i
=0; i
<aTestValues
[ index
].nRowData
; ++i
)
360 SCROW nRow
= aTestValues
[ index
].pData
[ i
].nStartRow
;
361 SCROW nEndRow
= aTestValues
[ index
].pData
[ i
].nEndRow
;
362 SCTAB nTab
= aTestValues
[ index
].pData
[ i
].nTab
;
363 int nExpectedHeight
= aTestValues
[ index
].pData
[ i
].nExpectedHeight
;
364 for ( ; nRow
<= nEndRow
; ++nRow
)
366 printf("\t checking row %d for height %d\n", nRow
, nExpectedHeight
);
367 int nHeight
= sc::TwipsToHMM( pDoc
->GetRowHeight(nRow
, nTab
, false) );
368 CPPUNIT_ASSERT_EQUAL(nExpectedHeight
, nHeight
);
374 ScExportTest::ScExportTest()
375 : m_aBaseString(RTL_CONSTASCII_USTRINGPARAM("/sc/qa/unit/data"))
379 void ScExportTest::setUp()
381 test::BootstrapFixture::setUp();
383 // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
384 // which is a private symbol to us, gets called
386 getMultiServiceFactory()->createInstance(rtl::OUString(
387 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Calc.SpreadsheetDocument")));
388 CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent
.is());
391 void ScExportTest::tearDown()
393 uno::Reference
< lang::XComponent
>( m_xCalcComponent
, UNO_QUERY_THROW
)->dispose();
394 test::BootstrapFixture::tearDown();
397 CPPUNIT_TEST_SUITE_REGISTRATION(ScExportTest
);
399 CPPUNIT_PLUGIN_IMPLEMENT();
401 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */