Impress Remote 1.0.5, tag sdremote-1.0.5
[LibreOffice.git] / sc / qa / unit / filters-test.cxx
blob755be75ef495524b0b51452d176ea2eb271110ce
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * Version: MPL 1.1 / GPLv3+ / LGPLv3+
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License or as specified alternatively below. You may obtain a copy of
8 * the License at http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
13 * License.
15 * Major Contributor(s):
16 * Copyright (C) 2010 Red Hat, Inc., Caolán McNamara <caolanm@redhat.com>
17 * (initial developer)
18 * Copyright (C) 2011 Markus Mohrhard <markus.mohrhard@googlemail.com>
20 * All Rights Reserved.
22 * For minor contributions see the git repository.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
26 * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
27 * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
28 * instead of those above.
31 #include <sal/config.h>
32 #include <unotest/filters-test.hxx>
33 #include <test/bootstrapfixture.hxx>
34 #include <rtl/strbuf.hxx>
35 #include <osl/file.hxx>
37 #include <sfx2/app.hxx>
38 #include <sfx2/docfilt.hxx>
39 #include <sfx2/docfile.hxx>
40 #include <sfx2/sfxmodelfactory.hxx>
41 #include <svl/stritem.hxx>
43 #define CALC_DEBUG_OUTPUT 0
44 #define TEST_BUG_FILES 0
46 #include "helper/qahelper.hxx"
48 #include "docsh.hxx"
49 #include "postit.hxx"
50 #include "patattr.hxx"
51 #include "scitems.hxx"
52 #include "document.hxx"
53 #include "cellform.hxx"
55 #define ODS_FORMAT_TYPE 50331943
56 #define XLS_FORMAT_TYPE 318767171
57 #define XLSX_FORMAT_TYPE 268959811
58 #define LOTUS123_FORMAT_TYPE 268435649
60 #define ODS 0
61 #define XLS 1
62 #define XLSX 2
63 #define LOTUS123 3
65 using namespace ::com::sun::star;
66 using namespace ::com::sun::star::uno;
68 namespace {
70 struct FileFormat {
71 const char* pName; const char* pFilterName; const char* pTypeName; unsigned int nFormatType;
74 FileFormat aFileFormats[] = {
75 { "ods" , "calc8", "", ODS_FORMAT_TYPE },
76 { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE },
77 { "xlsx", "Calc MS Excel 2007 XML" , "MS Excel 2007 XML", XLSX_FORMAT_TYPE },
78 { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE }
83 /* Implementation of Filters test */
85 class ScFiltersTest
86 : public test::FiltersTest
87 , public test::BootstrapFixture
89 public:
90 ScFiltersTest();
92 virtual bool load( const rtl::OUString &rFilter, const rtl::OUString &rURL,
93 const rtl::OUString &rUserData, unsigned int nFilterFlags,
94 unsigned int nClipboardID, unsigned int nFilterVersion);
96 ScDocShellRef load(const rtl::OUString &rFilter, const rtl::OUString &rURL,
97 const rtl::OUString &rUserData, const rtl::OUString& rTypeName,
98 unsigned int nFilterFlags, unsigned int nClipboardID, unsigned int nFilterVersion);
100 void createFileURL(const rtl::OUString& aFileBase, const rtl::OUString& aFileExtension, rtl::OUString& rFilePath);
101 void createCSVPath(const rtl::OUString& aFileBase, rtl::OUString& rFilePath);
103 virtual void setUp();
104 virtual void tearDown();
107 * Ensure CVEs remain unbroken
109 void testCVEs();
111 //ods, xls, xlsx filter tests
112 void testRangeNameODS(); // only test ods here, xls and xlsx in subsequent_filters-test
113 void testContentODS();
114 void testContentXLS();
115 void testContentXLSX();
116 void testContentLotus123();
118 #if TEST_BUG_FILES
119 //goes recursively through all files in this dir and tries to open them
120 void testDir(osl::Directory& rDir, sal_Int32 nType);
121 //test Bug Files and search for files that crash LibO
122 void testBugFiles();
123 void testBugFilesXLS();
124 void testBugFilesXLSX();
125 #endif
127 CPPUNIT_TEST_SUITE(ScFiltersTest);
128 CPPUNIT_TEST(testCVEs);
129 CPPUNIT_TEST(testRangeNameODS);
130 CPPUNIT_TEST(testContentODS);
131 CPPUNIT_TEST(testContentXLS);
132 CPPUNIT_TEST(testContentXLSX);
133 CPPUNIT_TEST(testContentLotus123);
135 #if TEST_BUG_FILES
136 CPPUNIT_TEST(testBugFiles);
137 CPPUNIT_TEST(testBugFilesXLS);
138 CPPUNIT_TEST(testBugFilesXLSX);
139 #endif
140 CPPUNIT_TEST_SUITE_END();
142 private:
143 ScDocShellRef loadDoc(const rtl::OUString& rName, sal_Int32 nFormat);
144 uno::Reference<uno::XInterface> m_xCalcComponent;
145 ::rtl::OUString m_aBaseString;
148 ScDocShellRef ScFiltersTest::load(const rtl::OUString &rFilter, const rtl::OUString &rURL,
149 const rtl::OUString &rUserData, const rtl::OUString& rTypeName,
150 unsigned int nFilterFlags, unsigned int nClipboardID, unsigned int nFilterVersion)
152 SfxFilter* pFilter = new SfxFilter(
153 rFilter,
154 rtl::OUString(), nFilterFlags, nClipboardID, rTypeName, 0, rtl::OUString(),
155 rUserData, rtl::OUString("private:factory/scalc*") );
156 pFilter->SetVersion(nFilterVersion);
158 ScDocShellRef xDocShRef = new ScDocShell;
159 xDocShRef->GetDocument()->EnableUserInteraction(false);
160 SfxMedium* pSrcMed = new SfxMedium(rURL, STREAM_STD_READ);
161 pSrcMed->UseInteractionHandler(false);
162 pSrcMed->SetFilter(pFilter);
163 if (!xDocShRef->DoLoad(pSrcMed))
165 xDocShRef->DoClose();
166 // load failed.
167 xDocShRef.Clear();
170 return xDocShRef;
173 bool ScFiltersTest::load(const rtl::OUString &rFilter, const rtl::OUString &rURL,
174 const rtl::OUString &rUserData, unsigned int nFilterFlags,
175 unsigned int nClipboardID, unsigned int nFilterVersion)
177 ScDocShellRef xDocShRef = load(rFilter, rURL, rUserData,
178 rtl::OUString(), nFilterFlags, nClipboardID, nFilterVersion);
179 bool bLoaded = xDocShRef.Is();
180 //reference counting of ScDocShellRef is very confused.
181 if (bLoaded)
182 xDocShRef->DoClose();
183 return bLoaded;
186 void ScFiltersTest::createFileURL(const rtl::OUString& aFileBase, const rtl::OUString& aFileExtension, rtl::OUString& rFilePath)
188 rtl::OUString aSep(RTL_CONSTASCII_USTRINGPARAM("/"));
189 rtl::OUStringBuffer aBuffer( getSrcRootURL() );
190 aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
191 aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
192 rFilePath = aBuffer.makeStringAndClear();
195 void ScFiltersTest::createCSVPath(const rtl::OUString& aFileBase, rtl::OUString& rCSVPath)
197 rtl::OUStringBuffer aBuffer(getSrcRootPath());
198 aBuffer.append(m_aBaseString).append(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("/contentCSV/")));
199 aBuffer.append(aFileBase).append(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("csv")));
200 rCSVPath = aBuffer.makeStringAndClear();
203 void ScFiltersTest::testCVEs()
205 #ifndef DISABLE_CVE_TESTS
206 testDir(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("Quattro Pro 6.0")),
207 getURLFromSrc("/sc/qa/unit/data/qpro/"), rtl::OUString());
209 //warning, the current "sylk filter" in sc (docsh.cxx) automatically
210 //chains on failure on trying as csv, rtf, etc. so "success" may
211 //not indicate that it imported as .slk.
212 testDir(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("SYLK")),
213 getURLFromSrc("/sc/qa/unit/data/slk/"), rtl::OUString());
215 testDir(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("MS Excel 97")),
216 getURLFromSrc("/sc/qa/unit/data/xls/"), rtl::OUString());
217 #endif
220 #if TEST_BUG_FILES
222 void ScFiltersTest::testDir(osl::Directory& rDir, sal_uInt32 nType)
224 rtl::OUString aFilterName(aFileFormats[nType].pFilterName, strlen(aFileFormats[nType].pFilterName), RTL_TEXTENCODING_UTF8) ;
225 rtl::OUString aFilterType(aFileFormats[nType].pTypeName, strlen(aFileFormats[nType].pTypeName), RTL_TEXTENCODING_UTF8);
227 osl::DirectoryItem aItem;
228 osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileURL|osl_FileStatus_Mask_Type);
229 while (rDir.getNextItem(aItem) == osl::FileBase::E_None)
231 aItem.getFileStatus(aFileStatus);
232 rtl::OUString sURL = aFileStatus.getFileURL();
233 std::cout << "File: " << rtl::OUStringToOString(sURL, RTL_TEXTENCODING_UTF8).getStr() << std::endl;
234 //rtl::OStringBuffer aMessage("Failed loading: ");
235 //aMessage.append(rtl::OUStringToOString(sURL, RTL_TEXTENCODING_UTF8));
237 unsigned int nFormatType = aFileFormats[nType].nFormatType;
238 unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
239 ScDocShellRef xDocSh = load(aFilterName, sURL, rtl::OUString(),
240 aFilterType, nFormatType, nClipboardId, SOFFICE_FILEFORMAT_CURRENT);
241 // use this only if you're sure that all files can be loaded
242 // pay attention to lock files
243 //CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), xDocSh.Is());
244 if (xDocSh.Is())
245 xDocSh->DoClose();
249 void ScFiltersTest::testBugFiles()
251 rtl::OUString aDirName = getURLFromSrc("/sc/qa/unit/data/bugODS/");
252 osl::Directory aDir(aDirName);
254 CPPUNIT_ASSERT(osl::FileBase::E_None == aDir.open());
255 testDir(aDir, 0);
258 void ScFiltersTest::testBugFilesXLS()
260 rtl::OUString aDirName = getURLFromSrc("/sc/qa/unit/data/bugXLS/");
261 osl::Directory aDir(aDirName);
263 CPPUNIT_ASSERT(osl::FileBase::E_None == aDir.open());
264 testDir(aDir, 1);
267 void ScFiltersTest::testBugFilesXLSX()
269 rtl::OUString aDirName = getURLFromSrc("/sc/qa/unit/data/bugXLSX/");
270 osl::Directory aDir(aDirName);
272 CPPUNIT_ASSERT(osl::FileBase::E_None == aDir.open());
273 testDir(aDir, 2);
276 #endif
278 namespace {
280 void testRangeNameImpl(ScDocument* pDoc)
282 //check one range data per sheet and one global more detailed
283 //add some more checks here
284 ScRangeData* pRangeData = pDoc->GetRangeName()->findByUpperName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("GLOBAL1")));
285 CPPUNIT_ASSERT_MESSAGE("range name Global1 not found", pRangeData);
286 double aValue;
287 pDoc->GetValue(1,0,0,aValue);
288 CPPUNIT_ASSERT_MESSAGE("range name Global1 should reference Sheet1.A1", aValue == 1);
289 pRangeData = pDoc->GetRangeName(0)->findByUpperName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LOCAL1")));
290 CPPUNIT_ASSERT_MESSAGE("range name Sheet1.Local1 not found", pRangeData);
291 pDoc->GetValue(1,2,0,aValue);
292 CPPUNIT_ASSERT_MESSAGE("range name Sheet1.Local1 should reference Sheet1.A3", aValue == 3);
293 pRangeData = pDoc->GetRangeName(1)->findByUpperName(rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("LOCAL2")));
294 CPPUNIT_ASSERT_MESSAGE("range name Sheet2.Local2 not found", pRangeData);
295 //check for correct results for the remaining formulas
296 pDoc->GetValue(1,1,0, aValue);
297 CPPUNIT_ASSERT_MESSAGE("=global2 should be 2", aValue == 2);
298 pDoc->GetValue(1,3,0, aValue);
299 CPPUNIT_ASSERT_MESSAGE("=local2 should be 4", aValue == 4);
300 pDoc->GetValue(2,0,0, aValue);
301 CPPUNIT_ASSERT_MESSAGE("=SUM(global3) should be 10", aValue == 10);
306 ScDocShellRef ScFiltersTest::loadDoc(const rtl::OUString& rName, sal_Int32 nFormat)
308 rtl::OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
309 rtl::OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
310 rtl::OUString aFileName;
311 createFileURL( rName, aFileExtension, aFileName );
312 rtl::OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
313 unsigned int nFormatType = aFileFormats[nFormat].nFormatType;
314 unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
315 ScDocShellRef xDocSh = load(aFilterName, aFileName, rtl::OUString(), aFilterType,
316 nFormatType, nClipboardId, SOFFICE_FILEFORMAT_CURRENT);
317 CPPUNIT_ASSERT(xDocSh.Is());
318 return xDocSh;
321 void ScFiltersTest::testRangeNameODS()
323 ScDocShellRef xDocSh = loadDoc("named-ranges-global.", ODS);
325 CPPUNIT_ASSERT_MESSAGE("Failed to load named-ranges-globals.*", xDocSh.Is());
327 xDocSh->DoHardRecalc(true);
329 ScDocument* pDoc = xDocSh->GetDocument();
330 testRangeNameImpl(pDoc);
332 rtl::OUString aSheet2CSV(RTL_CONSTASCII_USTRINGPARAM("rangeExp_Sheet2."));
333 rtl::OUString aCSVPath;
334 createCSVPath( aSheet2CSV, aCSVPath );
335 testFile( aCSVPath, pDoc, 1);
336 xDocSh->DoClose();
339 namespace {
341 void testContentImpl(ScDocument* pDoc, sal_Int32 nFormat ) //same code for ods, xls, xlsx
343 double fValue;
344 //check value import
345 pDoc->GetValue(0,0,0,fValue);
346 CPPUNIT_ASSERT_MESSAGE("value not imported correctly", fValue == 1);
347 pDoc->GetValue(0,1,0,fValue);
348 CPPUNIT_ASSERT_MESSAGE("value not imported correctly", fValue == 2);
349 rtl::OUString aString;
350 pDoc->GetString(1,0,0,aString);
352 //check string import
353 CPPUNIT_ASSERT_MESSAGE("string imported not correctly", aString == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("String1")));
354 pDoc->GetString(1,1,0,aString);
355 CPPUNIT_ASSERT_MESSAGE("string not imported correctly", aString == rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("String2")));
357 //check basic formula import
358 pDoc->GetValue(2,0,0,fValue);
359 CPPUNIT_ASSERT_MESSAGE("=2*3", fValue == 6);
360 pDoc->GetValue(2,1,0,fValue);
361 CPPUNIT_ASSERT_MESSAGE("=2+3", fValue == 5);
362 pDoc->GetValue(2,2,0,fValue);
363 CPPUNIT_ASSERT_MESSAGE("=2-3", fValue == -1);
364 pDoc->GetValue(2,3,0,fValue);
365 CPPUNIT_ASSERT_MESSAGE("=C1+C2", fValue == 11);
367 //check merged cells import
368 if(nFormat != LOTUS123)
370 SCCOL nCol = 4;
371 SCROW nRow = 1;
372 pDoc->ExtendMerge(4, 1, nCol, nRow, 0, false);
373 CPPUNIT_ASSERT_MESSAGE("merged cells are not imported", nCol == 5 && nRow == 2);
375 //check notes import
376 ScAddress aAddress(7, 2, 0);
377 ScPostIt* pNote = pDoc->GetNotes(aAddress.Tab())->findByAddress(aAddress);
378 CPPUNIT_ASSERT_MESSAGE("note not imported", pNote);
379 CPPUNIT_ASSERT_EQUAL_MESSAGE("note text not imported correctly", pNote->GetText(), rtl::OUString("Test"));
382 //add additional checks here
387 void ScFiltersTest::testContentODS()
389 ScDocShellRef xDocSh = loadDoc("universal-content.", ODS);
390 xDocSh->DoHardRecalc(true);
392 ScDocument* pDoc = xDocSh->GetDocument();
393 testContentImpl(pDoc, ODS);
394 xDocSh->DoClose();
397 void ScFiltersTest::testContentXLS()
399 ScDocShellRef xDocSh = loadDoc("universal-content.", XLS);
400 xDocSh->DoHardRecalc(true);
402 ScDocument* pDoc = xDocSh->GetDocument();
403 testContentImpl(pDoc, XLS);
404 xDocSh->DoClose();
407 void ScFiltersTest::testContentXLSX()
409 ScDocShellRef xDocSh = loadDoc("universal-content.", XLSX);
410 xDocSh->DoHardRecalc(true);
412 ScDocument* pDoc = xDocSh->GetDocument();
413 testContentImpl(pDoc, XLSX);
414 xDocSh->DoClose();
417 void ScFiltersTest::testContentLotus123()
419 ScDocShellRef xDocSh = loadDoc("universal-content.", LOTUS123);
420 xDocSh->DoHardRecalc(true);
422 ScDocument* pDoc = xDocSh->GetDocument();
423 CPPUNIT_ASSERT(pDoc);
424 testContentImpl(pDoc, LOTUS123);
425 xDocSh->DoClose();
428 ScFiltersTest::ScFiltersTest()
429 : m_aBaseString(RTL_CONSTASCII_USTRINGPARAM("/sc/qa/unit/data"))
433 void ScFiltersTest::setUp()
435 test::BootstrapFixture::setUp();
437 // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
438 // which is a private symbol to us, gets called
439 m_xCalcComponent =
440 getMultiServiceFactory()->createInstance(rtl::OUString(
441 RTL_CONSTASCII_USTRINGPARAM("com.sun.star.comp.Calc.SpreadsheetDocument")));
442 CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
445 void ScFiltersTest::tearDown()
447 uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
448 test::BootstrapFixture::tearDown();
451 CPPUNIT_TEST_SUITE_REGISTRATION(ScFiltersTest);
453 CPPUNIT_PLUGIN_IMPLEMENT();
455 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */