bump product version to 4.1.6.2
[LibreOffice.git] / sc / qa / unit / filters-test.cxx
blob8f245c2ccbc224a2207d5156adc62c3853031749
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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/.
8 */
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 "scdll.hxx"
17 #include <sfx2/app.hxx>
18 #include <sfx2/docfilt.hxx>
19 #include <sfx2/docfile.hxx>
20 #include <sfx2/sfxmodelfactory.hxx>
21 #include <svl/stritem.hxx>
23 #define CALC_DEBUG_OUTPUT 0
24 #define TEST_BUG_FILES 0
26 #include "helper/qahelper.hxx"
28 #include "docsh.hxx"
29 #include "postit.hxx"
30 #include "patattr.hxx"
31 #include "scitems.hxx"
32 #include "document.hxx"
33 #include "cellform.hxx"
34 #include "drwlayer.hxx"
35 #include "userdat.hxx"
36 #include <svx/svdpage.hxx>
38 using namespace ::com::sun::star;
39 using namespace ::com::sun::star::uno;
41 /* Implementation of Filters test */
43 class ScFiltersTest
44 : public test::FiltersTest
45 , public ScBootstrapFixture
47 public:
48 ScFiltersTest();
50 virtual void setUp();
51 virtual void tearDown();
53 virtual bool load( const OUString &rFilter, const OUString &rURL,
54 const OUString &rUserData, unsigned int nFilterFlags,
55 unsigned int nClipboardID, unsigned int nFilterVersion);
56 /**
57 * Ensure CVEs remain unbroken
59 void testCVEs();
61 //ods, xls, xlsx filter tests
62 void testRangeNameODS(); // only test ods here, xls and xlsx in subsequent_filters-test
63 void testContentODS();
64 void testContentXLS();
65 void testContentXLSX();
66 void testContentLotus123();
67 #if TEST_BUG_FILES
68 //goes recursively through all files in this dir and tries to open them
69 void testDir(osl::Directory& rDir, sal_Int32 nType);
70 //test Bug Files and search for files that crash LibO
71 void testBugFiles();
72 void testBugFilesXLS();
73 void testBugFilesXLSX();
74 #endif
75 void testLegacyCellAnchoredRotatedShape();
77 CPPUNIT_TEST_SUITE(ScFiltersTest);
78 CPPUNIT_TEST(testCVEs);
79 CPPUNIT_TEST(testRangeNameODS);
80 CPPUNIT_TEST(testContentODS);
81 CPPUNIT_TEST(testContentXLS);
82 CPPUNIT_TEST(testContentXLSX);
83 CPPUNIT_TEST(testContentLotus123);
84 CPPUNIT_TEST(testLegacyCellAnchoredRotatedShape);
86 #if TEST_BUG_FILES
87 CPPUNIT_TEST(testBugFiles);
88 CPPUNIT_TEST(testBugFilesXLS);
89 CPPUNIT_TEST(testBugFilesXLSX);
90 #endif
91 CPPUNIT_TEST_SUITE_END();
93 private:
94 uno::Reference<uno::XInterface> m_xCalcComponent;
97 bool ScFiltersTest::load(const OUString &rFilter, const OUString &rURL,
98 const OUString &rUserData, unsigned int nFilterFlags,
99 unsigned int nClipboardID, unsigned int nFilterVersion)
101 ScDocShellRef xDocShRef = ScBootstrapFixture::load(rURL, rFilter, rUserData,
102 OUString(), nFilterFlags, nClipboardID, nFilterVersion );
103 bool bLoaded = xDocShRef.Is();
104 //reference counting of ScDocShellRef is very confused.
105 if (bLoaded)
106 xDocShRef->DoClose();
107 return bLoaded;
110 void ScFiltersTest::testCVEs()
112 #ifndef DISABLE_CVE_TESTS
113 testDir(OUString("Quattro Pro 6.0"),
114 getURLFromSrc("/sc/qa/unit/data/qpro/"), OUString());
116 //warning, the current "sylk filter" in sc (docsh.cxx) automatically
117 //chains on failure on trying as csv, rtf, etc. so "success" may
118 //not indicate that it imported as .slk.
119 testDir(OUString("SYLK"),
120 getURLFromSrc("/sc/qa/unit/data/slk/"), OUString());
122 testDir(OUString("MS Excel 97"),
123 getURLFromSrc("/sc/qa/unit/data/xls/"), OUString());
124 #endif
127 #if TEST_BUG_FILES
129 void ScFiltersTest::testDir(osl::Directory& rDir, sal_uInt32 nType)
131 OUString aFilterName(aFileFormats[nType].pFilterName, strlen(aFileFormats[nType].pFilterName), RTL_TEXTENCODING_UTF8) ;
132 OUString aFilterType(aFileFormats[nType].pTypeName, strlen(aFileFormats[nType].pTypeName), RTL_TEXTENCODING_UTF8);
134 osl::DirectoryItem aItem;
135 osl::FileStatus aFileStatus(osl_FileStatus_Mask_FileURL|osl_FileStatus_Mask_Type);
136 while (rDir.getNextItem(aItem) == osl::FileBase::E_None)
138 aItem.getFileStatus(aFileStatus);
139 OUString sURL = aFileStatus.getFileURL();
140 std::cout << "File: " << OUStringToOString(sURL, RTL_TEXTENCODING_UTF8).getStr() << std::endl;
141 //OStringBuffer aMessage("Failed loading: ");
142 //aMessage.append(OUStringToOString(sURL, RTL_TEXTENCODING_UTF8));
144 unsigned int nFormatType = aFileFormats[nType].nFormatType;
145 unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
146 ScDocShellRef xDocSh = load(sURL, aFilterName, OUString(),
147 aFilterType, nFormatType, nClipboardId );
148 // use this only if you're sure that all files can be loaded
149 // pay attention to lock files
150 //CPPUNIT_ASSERT_MESSAGE(aMessage.getStr(), xDocSh.Is());
151 if (xDocSh.Is())
152 xDocSh->DoClose();
156 void ScFiltersTest::testBugFiles()
158 OUString aDirName = getURLFromSrc("/sc/qa/unit/data/bugODS/");
159 osl::Directory aDir(aDirName);
161 CPPUNIT_ASSERT(osl::FileBase::E_None == aDir.open());
162 testDir(aDir, 0);
165 void ScFiltersTest::testBugFilesXLS()
167 OUString aDirName = getURLFromSrc("/sc/qa/unit/data/bugXLS/");
168 osl::Directory aDir(aDirName);
170 CPPUNIT_ASSERT(osl::FileBase::E_None == aDir.open());
171 testDir(aDir, 1);
174 void ScFiltersTest::testBugFilesXLSX()
176 OUString aDirName = getURLFromSrc("/sc/qa/unit/data/bugXLSX/");
177 osl::Directory aDir(aDirName);
179 CPPUNIT_ASSERT(osl::FileBase::E_None == aDir.open());
180 testDir(aDir, 2);
183 #endif
185 namespace {
187 void testRangeNameImpl(ScDocument* pDoc)
189 //check one range data per sheet and one global more detailed
190 //add some more checks here
191 ScRangeData* pRangeData = pDoc->GetRangeName()->findByUpperName(OUString("GLOBAL1"));
192 CPPUNIT_ASSERT_MESSAGE("range name Global1 not found", pRangeData);
193 double aValue;
194 pDoc->GetValue(1,0,0,aValue);
195 CPPUNIT_ASSERT_MESSAGE("range name Global1 should reference Sheet1.A1", aValue == 1);
196 pRangeData = pDoc->GetRangeName(0)->findByUpperName(OUString("LOCAL1"));
197 CPPUNIT_ASSERT_MESSAGE("range name Sheet1.Local1 not found", pRangeData);
198 pDoc->GetValue(1,2,0,aValue);
199 CPPUNIT_ASSERT_MESSAGE("range name Sheet1.Local1 should reference Sheet1.A3", aValue == 3);
200 pRangeData = pDoc->GetRangeName(1)->findByUpperName(OUString("LOCAL2"));
201 CPPUNIT_ASSERT_MESSAGE("range name Sheet2.Local2 not found", pRangeData);
202 //check for correct results for the remaining formulas
203 pDoc->GetValue(1,1,0, aValue);
204 CPPUNIT_ASSERT_MESSAGE("=global2 should be 2", aValue == 2);
205 pDoc->GetValue(1,3,0, aValue);
206 CPPUNIT_ASSERT_MESSAGE("=local2 should be 4", aValue == 4);
207 pDoc->GetValue(2,0,0, aValue);
208 CPPUNIT_ASSERT_MESSAGE("=SUM(global3) should be 10", aValue == 10);
213 void ScFiltersTest::testRangeNameODS()
215 ScDocShellRef xDocSh = loadDoc("named-ranges-global.", ODS);
217 CPPUNIT_ASSERT_MESSAGE("Failed to load named-ranges-globals.*", xDocSh.Is());
219 xDocSh->DoHardRecalc(true);
221 ScDocument* pDoc = xDocSh->GetDocument();
222 testRangeNameImpl(pDoc);
224 OUString aSheet2CSV("rangeExp_Sheet2.");
225 OUString aCSVPath;
226 createCSVPath( aSheet2CSV, aCSVPath );
227 testFile( aCSVPath, pDoc, 1);
228 xDocSh->DoClose();
231 namespace {
233 void testContentImpl(ScDocument* pDoc, sal_Int32 nFormat ) //same code for ods, xls, xlsx
235 double fValue;
236 //check value import
237 pDoc->GetValue(0,0,0,fValue);
238 CPPUNIT_ASSERT_MESSAGE("value not imported correctly", fValue == 1);
239 pDoc->GetValue(0,1,0,fValue);
240 CPPUNIT_ASSERT_MESSAGE("value not imported correctly", fValue == 2);
241 OUString aString = pDoc->GetString(1, 0, 0);
243 //check string import
244 CPPUNIT_ASSERT_MESSAGE("string imported not correctly", aString == OUString("String1"));
245 aString = pDoc->GetString(1, 1, 0);
246 CPPUNIT_ASSERT_MESSAGE("string not imported correctly", aString == OUString("String2"));
248 //check basic formula import
249 pDoc->GetValue(2,0,0,fValue);
250 CPPUNIT_ASSERT_MESSAGE("=2*3", fValue == 6);
251 pDoc->GetValue(2,1,0,fValue);
252 CPPUNIT_ASSERT_MESSAGE("=2+3", fValue == 5);
253 pDoc->GetValue(2,2,0,fValue);
254 CPPUNIT_ASSERT_MESSAGE("=2-3", fValue == -1);
255 pDoc->GetValue(2,3,0,fValue);
256 CPPUNIT_ASSERT_MESSAGE("=C1+C2", fValue == 11);
258 //check merged cells import
259 if(nFormat != LOTUS123)
261 SCCOL nCol = 4;
262 SCROW nRow = 1;
263 pDoc->ExtendMerge(4, 1, nCol, nRow, 0, false);
264 CPPUNIT_ASSERT_MESSAGE("merged cells are not imported", nCol == 5 && nRow == 2);
266 //check notes import
267 ScAddress aAddress(7, 2, 0);
268 ScPostIt* pNote = pDoc->GetNotes(aAddress.Tab())->findByAddress(aAddress);
269 CPPUNIT_ASSERT_MESSAGE("note not imported", pNote);
270 CPPUNIT_ASSERT_EQUAL_MESSAGE("note text not imported correctly", pNote->GetText(), OUString("Test"));
273 //add additional checks here
278 void ScFiltersTest::testContentODS()
280 ScDocShellRef xDocSh = loadDoc("universal-content.", ODS);
281 xDocSh->DoHardRecalc(true);
283 ScDocument* pDoc = xDocSh->GetDocument();
284 testContentImpl(pDoc, ODS);
285 xDocSh->DoClose();
288 void ScFiltersTest::testContentXLS()
290 ScDocShellRef xDocSh = loadDoc("universal-content.", XLS);
291 xDocSh->DoHardRecalc(true);
293 ScDocument* pDoc = xDocSh->GetDocument();
294 testContentImpl(pDoc, XLS);
295 xDocSh->DoClose();
298 void ScFiltersTest::testContentXLSX()
300 ScDocShellRef xDocSh = loadDoc("universal-content.", XLSX);
301 xDocSh->DoHardRecalc(true);
303 ScDocument* pDoc = xDocSh->GetDocument();
304 testContentImpl(pDoc, XLSX);
305 xDocSh->DoClose();
308 void ScFiltersTest::testContentLotus123()
310 ScDocShellRef xDocSh = loadDoc("universal-content.", LOTUS123);
311 xDocSh->DoHardRecalc(true);
313 ScDocument* pDoc = xDocSh->GetDocument();
314 CPPUNIT_ASSERT(pDoc);
315 testContentImpl(pDoc, LOTUS123);
316 xDocSh->DoClose();
318 void impl_testLegacyCellAnchoredRotatedShape( ScDocument* pDoc, Rectangle& aRect, ScDrawObjData& aAnchor, long TOLERANCE = 30 /* 30 hmm */ )
320 ScDrawLayer* pDrawLayer = pDoc->GetDrawLayer();
321 CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer);
322 SdrPage* pPage = pDrawLayer->GetPage(0);
323 CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage);
324 CPPUNIT_ASSERT_EQUAL( sal_uIntPtr(1), pPage->GetObjCount() );
326 SdrObject* pObj = pPage->GetObj(0);
327 const Rectangle& aSnap = pObj->GetSnapRect();
328 printf("expected height %ld actual %ld\n", aRect.GetHeight(), aSnap.GetHeight() );
329 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.GetHeight(), aSnap.GetHeight(), TOLERANCE ) );
330 printf("expected width %ld actual %ld\n", aRect.GetWidth(), aSnap.GetWidth() );
331 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.GetWidth(), aSnap.GetWidth(), TOLERANCE ) );
332 printf("expected left %ld actual %ld\n", aRect.Left(), aSnap.Left() );
333 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.Left(), aSnap.Left(), TOLERANCE ) );
334 printf("expected right %ld actual %ld\n", aRect.Top(), aSnap.Top() );
335 CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.Top(), aSnap.Top(), TOLERANCE ) );
338 ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
339 printf("expected startrow %" SAL_PRIdINT32 " actual %" SAL_PRIdINT32 "\n", aAnchor.maStart.Row(), pData->maStart.Row() );
340 CPPUNIT_ASSERT_EQUAL( aAnchor.maStart.Row(), pData->maStart.Row() );
341 printf("expected startcol %d actual %d\n", aAnchor.maStart.Col(), pData->maStart.Col() );
342 CPPUNIT_ASSERT_EQUAL( aAnchor.maStart.Col(), pData->maStart.Col() );
343 printf("expected endrow %" SAL_PRIdINT32 " actual %" SAL_PRIdINT32 "\n", aAnchor.maEnd.Row(), pData->maEnd.Row() );
344 CPPUNIT_ASSERT_EQUAL( aAnchor.maEnd.Row(), pData->maEnd.Row() );
345 printf("expected endcol %d actual %d\n", aAnchor.maEnd.Col(), pData->maEnd.Col() );
346 CPPUNIT_ASSERT_EQUAL( aAnchor.maEnd.Col(), pData->maEnd.Col() );
349 void ScFiltersTest::testLegacyCellAnchoredRotatedShape()
352 // This example doc contains cell anchored shape that is rotated, the
353 // rotated shape is in fact cliped by the sheet boundries ( and thus
354 // is a good edge case test to see if we import it still correctly )
355 ScDocShellRef xDocSh = loadDoc("legacycellanchoredrotatedclippedshape.", ODS);
357 ScDocument* pDoc = xDocSh->GetDocument();
358 CPPUNIT_ASSERT(pDoc);
359 // ensure the imported legacy rotated shape is in the expected position
360 Rectangle aRect( 6000, -2000, 8000, 4000 );
361 // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in
362 // terms of the rotated shape ) is more or less contains the correct info
363 ScDrawObjData aAnchor;
364 aAnchor.maStart.SetRow( 0 );
365 aAnchor.maStart.SetCol( 5 );
366 aAnchor.maEnd.SetRow( 3 );
367 aAnchor.maEnd.SetCol( 7 );
368 impl_testLegacyCellAnchoredRotatedShape( pDoc, aRect, aAnchor );
369 // test save and reload
370 // for some reason having this test in subsequent_export-test.cxx causes
371 // a core dump in editeng ( so moved to here )
372 xDocSh = saveAndReload( &(*xDocSh), ODS);
373 pDoc = xDocSh->GetDocument();
374 CPPUNIT_ASSERT(pDoc);
375 impl_testLegacyCellAnchoredRotatedShape( pDoc, aRect, aAnchor );
378 // This example doc contains cell anchored shape that is rotated, the
379 // rotated shape is in fact clipped by the sheet boundries, additionally
380 // the shape is completely hidden because the rows the shape occupies
381 // are hidden
382 ScDocShellRef xDocSh = loadDoc("legacycellanchoredrotatedhiddenshape.", ODS, true);
383 ScDocument* pDoc = xDocSh->GetDocument();
384 CPPUNIT_ASSERT(pDoc);
385 // ensure the imported legacy rotated shape is in the expected position
386 // when a shape is fully hidden reloading seems to result is in some errors, usually
387 // ( same but different error happens pre-patch ) - we should do better here, I regard it
388 // as a pre-existing bug though ( #FIXME )
389 //Rectangle aRect( 6000, -2000, 8000, 4000 ); // proper dimensions
390 Rectangle aRect( 6000, -2000, 7430, 4000 );
391 // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in
392 // terms of the rotated shape ) is more or less contains the correct info
393 ScDrawObjData aAnchor;
394 aAnchor.maStart.SetRow( 0 );
395 aAnchor.maStart.SetCol( 5 );
396 aAnchor.maEnd.SetRow( 3 );
397 aAnchor.maEnd.SetCol( 7 );
398 pDoc->ShowRows(0, 9, 0, true); // show relavent rows
399 pDoc->SetDrawPageSize(0); // trigger recalcpos
401 // apply hefty ( 1 mm ) tolerence here, as some opensuse tinderbox
402 // failing
403 impl_testLegacyCellAnchoredRotatedShape( pDoc, aRect, aAnchor, 100 );
404 xDocSh->DoClose();
407 // This example doc contains cell anchored shape that is rotated
408 ScDocShellRef xDocSh = loadDoc("legacycellanchoredrotatedshape.", ODS);
410 ScDocument* pDoc = xDocSh->GetDocument();
411 CPPUNIT_ASSERT(pDoc);
412 // ensure the imported legacy rotated shape is in the expected position
413 Rectangle aRect( 6000, 3000, 8000, 9000 );
414 // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in
415 // terms of the rotated shape ) is more or less contains the correct info
417 ScDrawObjData aAnchor;
418 aAnchor.maStart.SetRow( 3 );
419 aAnchor.maStart.SetCol( 6 );
420 aAnchor.maEnd.SetRow( 9 );
421 aAnchor.maEnd.SetCol( 7 );
422 // test import
423 impl_testLegacyCellAnchoredRotatedShape( pDoc, aRect, aAnchor );
424 // test save and reload
425 xDocSh = saveAndReload( &(*xDocSh), ODS);
426 pDoc = xDocSh->GetDocument();
427 CPPUNIT_ASSERT(pDoc);
428 impl_testLegacyCellAnchoredRotatedShape( pDoc, aRect, aAnchor );
432 ScFiltersTest::ScFiltersTest()
433 : ScBootstrapFixture( "/sc/qa/unit/data" )
437 void ScFiltersTest::setUp()
439 test::BootstrapFixture::setUp();
441 // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
442 // which is a private symbol to us, gets called
443 m_xCalcComponent =
444 getMultiServiceFactory()->createInstance(OUString("com.sun.star.comp.Calc.SpreadsheetDocument"));
445 CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
448 void ScFiltersTest::tearDown()
450 uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
451 test::BootstrapFixture::tearDown();
454 CPPUNIT_TEST_SUITE_REGISTRATION(ScFiltersTest);
456 CPPUNIT_PLUGIN_IMPLEMENT();
458 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */