LCOV - code coverage report
Current view: top level - sc/qa/unit - filters-test.cxx (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 416 425 97.9 %
Date: 2015-06-13 12:38:46 Functions: 37 38 97.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       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             :  */
       9             : 
      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>
      15             : 
      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>
      22             : 
      23             : #include "helper/qahelper.hxx"
      24             : 
      25             : #include "docsh.hxx"
      26             : #include "inputopt.hxx"
      27             : #include "postit.hxx"
      28             : #include "patattr.hxx"
      29             : #include "scitems.hxx"
      30             : #include "document.hxx"
      31             : #include "cellform.hxx"
      32             : #include "drwlayer.hxx"
      33             : #include "userdat.hxx"
      34             : #include "formulacell.hxx"
      35             : #include "tabprotection.hxx"
      36             : #include <dbdocfun.hxx>
      37             : #include <globalnames.hxx>
      38             : #include <dbdata.hxx>
      39             : #include <sortparam.hxx>
      40             : #include "scopetools.hxx"
      41             : 
      42             : #include <svx/svdpage.hxx>
      43             : 
      44             : using namespace ::com::sun::star;
      45             : using namespace ::com::sun::star::uno;
      46             : 
      47             : /* Implementation of Filters test */
      48             : 
      49          34 : class ScFiltersTest
      50             :     : public test::FiltersTest
      51             :     , public ScBootstrapFixture
      52             : {
      53             : public:
      54             :     ScFiltersTest();
      55             : 
      56             :     virtual void setUp() SAL_OVERRIDE;
      57             :     virtual void tearDown() SAL_OVERRIDE;
      58             : 
      59             :     virtual bool load( const OUString &rFilter, const OUString &rURL,
      60             :         const OUString &rUserData, SfxFilterFlags nFilterFlags,
      61             :         SotClipboardFormatId nClipboardID, unsigned int nFilterVersion) SAL_OVERRIDE;
      62             :     /**
      63             :      * Ensure CVEs remain unbroken
      64             :      */
      65             :     void testCVEs();
      66             : 
      67             :     //ods, xls, xlsx filter tests
      68             :     void testRangeNameODS(); // only test ods here, xls and xlsx in subsequent_filters-test
      69             :     void testContentODS();
      70             :     void testContentXLS();
      71             :     void testContentXLSX();
      72             :     void testContentXLSXStrict(); // strict OOXML
      73             :     void testContentLotus123();
      74             :     void testContentDIF();
      75             :     void testContentXLSB();
      76             :     //void testContentXLS_XML();
      77             :     void testSharedFormulaXLS();
      78             :     void testSharedFormulaXLSX();
      79             :     void testSheetNamesXLSX();
      80             :     void testLegacyCellAnchoredRotatedShape();
      81             :     void testEnhancedProtectionXLS();
      82             :     void testEnhancedProtectionXLSX();
      83             :     void testSortWithSharedFormulasODS();
      84             :     void testSortWithSheetExternalReferencesODS();
      85             :     void testSortWithSheetExternalReferencesODS_Impl( ScDocShellRef xDocShRef, SCROW nRow1, SCROW nRow2,
      86             :             bool bCheckRelativeInSheet );
      87             : 
      88           2 :     CPPUNIT_TEST_SUITE(ScFiltersTest);
      89           1 :     CPPUNIT_TEST(testCVEs);
      90           1 :     CPPUNIT_TEST(testRangeNameODS);
      91           1 :     CPPUNIT_TEST(testContentODS);
      92           1 :     CPPUNIT_TEST(testContentXLS);
      93           1 :     CPPUNIT_TEST(testContentXLSX);
      94           1 :     CPPUNIT_TEST(testContentXLSXStrict);
      95           1 :     CPPUNIT_TEST(testContentLotus123);
      96           1 :     CPPUNIT_TEST(testContentDIF);
      97           1 :     CPPUNIT_TEST(testContentXLSB);
      98             :     //CPPUNIT_TEST(testContentXLS_XML);
      99           1 :     CPPUNIT_TEST(testSharedFormulaXLS);
     100           1 :     CPPUNIT_TEST(testSharedFormulaXLSX);
     101           1 :     CPPUNIT_TEST(testSheetNamesXLSX);
     102           1 :     CPPUNIT_TEST(testLegacyCellAnchoredRotatedShape);
     103           1 :     CPPUNIT_TEST(testEnhancedProtectionXLS);
     104           1 :     CPPUNIT_TEST(testEnhancedProtectionXLSX);
     105           1 :     CPPUNIT_TEST(testSortWithSharedFormulasODS);
     106           1 :     CPPUNIT_TEST(testSortWithSheetExternalReferencesODS);
     107             : 
     108           5 :     CPPUNIT_TEST_SUITE_END();
     109             : 
     110             : private:
     111             :     uno::Reference<uno::XInterface> m_xCalcComponent;
     112             :     bool mbUpdateReferenceOnSort; ///< Remember the configuration option so that we can set it back.
     113             : };
     114             : 
     115          25 : bool ScFiltersTest::load(const OUString &rFilter, const OUString &rURL,
     116             :     const OUString &rUserData, SfxFilterFlags nFilterFlags,
     117             :     SotClipboardFormatId nClipboardID, unsigned int nFilterVersion)
     118             : {
     119             :     ScDocShellRef xDocShRef = ScBootstrapFixture::load(rURL, rFilter, rUserData,
     120          25 :         OUString(), nFilterFlags, nClipboardID, nFilterVersion );
     121          25 :     bool bLoaded = xDocShRef.Is();
     122             :     //reference counting of ScDocShellRef is very confused.
     123          25 :     if (bLoaded)
     124          21 :         xDocShRef->DoClose();
     125          25 :     return bLoaded;
     126             : }
     127             : 
     128           1 : void ScFiltersTest::testCVEs()
     129             : {
     130             : #ifndef DISABLE_CVE_TESTS
     131             :     testDir(OUString("Quattro Pro 6.0"),
     132           1 :         getURLFromSrc("/sc/qa/unit/data/qpro/"), OUString());
     133             : 
     134             :     //warning, the current "sylk filter" in sc (docsh.cxx) automatically
     135             :     //chains on failure on trying as csv, rtf, etc. so "success" may
     136             :     //not indicate that it imported as .slk.
     137             :     testDir(OUString("SYLK"),
     138           1 :         getURLFromSrc("/sc/qa/unit/data/slk/"), OUString());
     139             : 
     140             :     testDir(OUString("MS Excel 97"),
     141           1 :         getURLFromSrc("/sc/qa/unit/data/xls/"), OUString());
     142             : 
     143             :     testDir(OUString("dBase"),
     144           1 :         getURLFromSrc("/sc/qa/unit/data/dbf/"), OUString());
     145             : 
     146             :     testDir(OUString("Lotus"),
     147           1 :         getURLFromSrc("/sc/qa/unit/data/wks/"), OUString());
     148             : 
     149             : #endif
     150           1 : }
     151             : 
     152             : namespace {
     153             : 
     154           1 : void testRangeNameImpl(ScDocument& rDoc)
     155             : {
     156             :     //check one range data per sheet and one global more detailed
     157             :     //add some more checks here
     158           1 :     ScRangeData* pRangeData = rDoc.GetRangeName()->findByUpperName(OUString("GLOBAL1"));
     159           1 :     CPPUNIT_ASSERT_MESSAGE("range name Global1 not found", pRangeData);
     160             :     double aValue;
     161           1 :     rDoc.GetValue(1,0,0,aValue);
     162           1 :     CPPUNIT_ASSERT_MESSAGE("range name Global1 should reference Sheet1.A1", aValue == 1);
     163           1 :     pRangeData = rDoc.GetRangeName(0)->findByUpperName(OUString("LOCAL1"));
     164           1 :     CPPUNIT_ASSERT_MESSAGE("range name Sheet1.Local1 not found", pRangeData);
     165           1 :     rDoc.GetValue(1,2,0,aValue);
     166           1 :     CPPUNIT_ASSERT_MESSAGE("range name Sheet1.Local1 should reference Sheet1.A3", aValue == 3);
     167           1 :     pRangeData = rDoc.GetRangeName(1)->findByUpperName(OUString("LOCAL2"));
     168           1 :     CPPUNIT_ASSERT_MESSAGE("range name Sheet2.Local2 not found", pRangeData);
     169             :     //check for correct results for the remaining formulas
     170           1 :     rDoc.GetValue(1,1,0, aValue);
     171           1 :     CPPUNIT_ASSERT_MESSAGE("=global2 should be 2", aValue == 2);
     172           1 :     rDoc.GetValue(1,3,0, aValue);
     173           1 :     CPPUNIT_ASSERT_MESSAGE("=local2 should be 4", aValue == 4);
     174           1 :     rDoc.GetValue(2,0,0, aValue);
     175           1 :     CPPUNIT_ASSERT_MESSAGE("=SUM(global3) should be 10", aValue == 10);
     176           1 : }
     177             : 
     178             : }
     179             : 
     180           1 : void ScFiltersTest::testRangeNameODS()
     181             : {
     182           1 :     ScDocShellRef xDocSh = loadDoc("named-ranges-global.", ODS);
     183             : 
     184           1 :     CPPUNIT_ASSERT_MESSAGE("Failed to load named-ranges-globals.*", xDocSh.Is());
     185             : 
     186           1 :     xDocSh->DoHardRecalc(true);
     187             : 
     188           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     189           1 :     testRangeNameImpl(rDoc);
     190             : 
     191           2 :     OUString aSheet2CSV("rangeExp_Sheet2.");
     192           2 :     OUString aCSVPath;
     193           1 :     createCSVPath( aSheet2CSV, aCSVPath );
     194           1 :     testFile( aCSVPath, rDoc, 1);
     195           2 :     xDocSh->DoClose();
     196           1 : }
     197             : 
     198             : namespace {
     199             : 
     200           6 : void testContentImpl(ScDocument& rDoc, sal_Int32 nFormat ) //same code for ods, xls, xlsx
     201             : {
     202             :     double fValue;
     203             :     //check value import
     204           6 :     rDoc.GetValue(0,0,0,fValue);
     205           6 :     CPPUNIT_ASSERT_MESSAGE("value not imported correctly", fValue == 1);
     206           6 :     rDoc.GetValue(0,1,0,fValue);
     207           6 :     CPPUNIT_ASSERT_MESSAGE("value not imported correctly", fValue == 2);
     208           6 :     OUString aString = rDoc.GetString(1, 0, 0);
     209             : 
     210             :     //check string import
     211           6 :     CPPUNIT_ASSERT_MESSAGE("string imported not correctly", aString == "String1");
     212           6 :     aString = rDoc.GetString(1, 1, 0);
     213           6 :     CPPUNIT_ASSERT_MESSAGE("string not imported correctly", aString == "String2");
     214             : 
     215             :     //check basic formula import
     216             :     // in case of DIF it just contains values
     217           6 :     rDoc.GetValue(2,0,0,fValue);
     218           6 :     CPPUNIT_ASSERT_MESSAGE("=2*3", fValue == 6);
     219           6 :     rDoc.GetValue(2,1,0,fValue);
     220           6 :     CPPUNIT_ASSERT_MESSAGE("=2+3", fValue == 5);
     221           6 :     rDoc.GetValue(2,2,0,fValue);
     222           6 :     CPPUNIT_ASSERT_MESSAGE("=2-3", fValue == -1);
     223           6 :     rDoc.GetValue(2,3,0,fValue);
     224           6 :     CPPUNIT_ASSERT_MESSAGE("=C1+C2", fValue == 11);
     225             : 
     226             :     //check merged cells import
     227           6 :     if(nFormat != LOTUS123 && nFormat != DIF)
     228             :     {
     229           5 :         SCCOL nCol = 4;
     230           5 :         SCROW nRow = 1;
     231           5 :         rDoc.ExtendMerge(4, 1, nCol, nRow, 0, false);
     232           5 :         CPPUNIT_ASSERT_MESSAGE("merged cells are not imported", nCol == 5 && nRow == 2);
     233             : 
     234             :         //check notes import
     235           5 :         ScAddress aAddress(7, 2, 0);
     236           5 :         ScPostIt* pNote = rDoc.GetNote(aAddress);
     237           5 :         CPPUNIT_ASSERT_MESSAGE("note not imported", pNote);
     238           5 :         CPPUNIT_ASSERT_EQUAL_MESSAGE("note text not imported correctly", pNote->GetText(), OUString("Test"));
     239           6 :     }
     240             : 
     241             :     //add additional checks here
     242           6 : }
     243             : 
     244             : }
     245             : 
     246           1 : void ScFiltersTest::testContentODS()
     247             : {
     248           1 :     ScDocShellRef xDocSh = loadDoc("universal-content.", ODS);
     249           1 :     xDocSh->DoHardRecalc(true);
     250             : 
     251           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     252           1 :     testContentImpl(rDoc, ODS);
     253           1 :     xDocSh->DoClose();
     254           1 : }
     255             : 
     256           1 : void ScFiltersTest::testContentXLS()
     257             : {
     258           1 :     ScDocShellRef xDocSh = loadDoc("universal-content.", XLS);
     259           1 :     xDocSh->DoHardRecalc(true);
     260             : 
     261           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     262           1 :     testContentImpl(rDoc, XLS);
     263           1 :     xDocSh->DoClose();
     264           1 : }
     265             : 
     266           1 : void ScFiltersTest::testContentXLSX()
     267             : {
     268           1 :     ScDocShellRef xDocSh = loadDoc("universal-content.", XLSX);
     269           1 :     xDocSh->DoHardRecalc(true);
     270             : 
     271           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     272           1 :     testContentImpl(rDoc, XLSX);
     273           1 :     xDocSh->DoClose();
     274           1 : }
     275             : 
     276           1 : void ScFiltersTest::testContentXLSXStrict()
     277             : {
     278           1 :     ScDocShellRef xDocSh = loadDoc("universal-content-strict.", XLSX);
     279           1 :     xDocSh->DoHardRecalc(true);
     280             : 
     281           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     282           1 :     testContentImpl(rDoc, XLSX);
     283           1 :     xDocSh->DoClose();
     284           1 : }
     285             : 
     286           1 : void ScFiltersTest::testContentLotus123()
     287             : {
     288           1 :     ScDocShellRef xDocSh = loadDoc("universal-content.", LOTUS123);
     289           1 :     xDocSh->DoHardRecalc(true);
     290             : 
     291           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     292           1 :     CPPUNIT_ASSERT(&rDoc);
     293           1 :     testContentImpl(rDoc, LOTUS123);
     294           1 :     xDocSh->DoClose();
     295           1 : }
     296             : 
     297           1 : void ScFiltersTest::testContentDIF()
     298             : {
     299           1 :     ScDocShellRef xDocSh = loadDoc("universal-content.", DIF);
     300             : 
     301           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     302           1 :     CPPUNIT_ASSERT(&rDoc);
     303           1 :     xDocSh->DoClose();
     304           1 : }
     305             : 
     306           1 : void ScFiltersTest::testContentXLSB()
     307             : {
     308           1 :     ScDocShellRef xDocSh = loadDoc("universal-content.", XLSB);
     309           1 :     xDocSh->DoHardRecalc(true);
     310             : 
     311           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     312           1 :     testContentImpl(rDoc, XLSB);
     313           1 :     xDocSh->DoClose();
     314           1 : }
     315             : 
     316             : // void ScFiltersTest::testContentXLS_XML()
     317             : // {
     318             : //     ScDocShellRef xDocSh = loadDoc("universal-content.", XLS_XML);
     319             : //     CPPUNIT_ASSERT(xDocSh);
     320             : //
     321             : //     ScDocument& rDoc = xDocSh->GetDocument();
     322             : //     CPPUNIT_ASSERT(&rDoc);
     323             : //     testContentImpl(pDoc, XLS_XML);
     324             : //     xDocSh->DoClose();
     325             : // }
     326             : 
     327           1 : void ScFiltersTest::testSharedFormulaXLS()
     328             : {
     329           1 :     ScDocShellRef xDocSh = loadDoc("shared-formula/basic.", XLS);
     330           1 :     CPPUNIT_ASSERT(xDocSh.Is());
     331           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     332           1 :     xDocSh->DoHardRecalc(true);
     333             :     // Check the results of formula cells in the shared formula range.
     334          19 :     for (SCROW i = 1; i <= 18; ++i)
     335             :     {
     336          18 :         double fVal = rDoc.GetValue(ScAddress(1,i,0));
     337          18 :         double fCheck = i*10.0;
     338          18 :         CPPUNIT_ASSERT_EQUAL(fCheck, fVal);
     339             :     }
     340             : 
     341           1 :     ScFormulaCell* pCell = rDoc.GetFormulaCell(ScAddress(1,18,0));
     342           1 :     CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pCell);
     343           2 :     ScFormulaCellGroupRef xGroup = pCell->GetCellGroup();
     344           1 :     CPPUNIT_ASSERT_MESSAGE("This cell should be a part of a cell group.", xGroup);
     345           1 :     CPPUNIT_ASSERT_MESSAGE("Incorrect group geometry.", xGroup->mpTopCell->aPos.Row() == 1 && xGroup->mnLength == 18);
     346             : 
     347           1 :     xDocSh->DoClose();
     348             : 
     349             :     // The following file contains shared formula whose range is inaccurate.
     350             :     // Excel can easily mess up shared formula ranges, so we need to be able
     351             :     // to handle these wrong ranges that Excel stores.
     352             : 
     353           1 :     xDocSh = loadDoc("shared-formula/gap.", XLS);
     354           1 :     CPPUNIT_ASSERT(xDocSh.Is());
     355           1 :     ScDocument& rDoc2 = xDocSh->GetDocument();
     356           1 :     rDoc2.CalcAll();
     357             : 
     358           1 :     if (!checkFormula(rDoc2, ScAddress(1,0,0), "A1*20"))
     359           0 :         CPPUNIT_FAIL("Wrong formula.");
     360             : 
     361           1 :     if (!checkFormula(rDoc2, ScAddress(1,1,0), "A2*20"))
     362           0 :         CPPUNIT_FAIL("Wrong formula.");
     363             : 
     364           1 :     if (!checkFormula(rDoc2, ScAddress(1,2,0), "A3*20"))
     365           0 :         CPPUNIT_FAIL("Wrong formula.");
     366             : 
     367             :     // There is an intentional gap at row 4.
     368             : 
     369           1 :     if (!checkFormula(rDoc2, ScAddress(1,4,0), "A5*20"))
     370           0 :         CPPUNIT_FAIL("Wrong formula.");
     371             : 
     372           1 :     if (!checkFormula(rDoc2, ScAddress(1,5,0), "A6*20"))
     373           0 :         CPPUNIT_FAIL("Wrong formula.");
     374             : 
     375           1 :     if (!checkFormula(rDoc2, ScAddress(1,6,0), "A7*20"))
     376           0 :         CPPUNIT_FAIL("Wrong formula.");
     377             : 
     378           1 :     if (!checkFormula(rDoc2, ScAddress(1,7,0), "A8*20"))
     379           0 :         CPPUNIT_FAIL("Wrong formula.");
     380             : 
     381             :     // We re-group formula cells on load. Let's check that as well.
     382             : 
     383           1 :     ScFormulaCell* pFC = rDoc2.GetFormulaCell(ScAddress(1,0,0));
     384           1 :     CPPUNIT_ASSERT_MESSAGE("Failed to fetch formula cell.", pFC);
     385           1 :     CPPUNIT_ASSERT_MESSAGE("This should be the top cell in formula group.", pFC->IsSharedTop());
     386           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), pFC->GetSharedLength());
     387             : 
     388           1 :     pFC = rDoc2.GetFormulaCell(ScAddress(1,4,0));
     389           1 :     CPPUNIT_ASSERT_MESSAGE("Failed to fetch formula cell.", pFC);
     390           1 :     CPPUNIT_ASSERT_MESSAGE("This should be the top cell in formula group.", pFC->IsSharedTop());
     391           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(4), pFC->GetSharedLength());
     392             : 
     393           2 :     xDocSh->DoClose();
     394           1 : }
     395             : 
     396           1 : void ScFiltersTest::testSharedFormulaXLSX()
     397             : {
     398           1 :     ScDocShellRef xDocSh = loadDoc("shared-formula/basic.", XLSX);
     399           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     400           1 :     CPPUNIT_ASSERT(&rDoc);
     401           1 :     xDocSh->DoHardRecalc(true);
     402             :     // Check the results of formula cells in the shared formula range.
     403          19 :     for (SCROW i = 1; i <= 18; ++i)
     404             :     {
     405          18 :         double fVal = rDoc.GetValue(ScAddress(1,i,0));
     406          18 :         double fCheck = i*10.0;
     407          18 :         CPPUNIT_ASSERT_EQUAL(fCheck, fVal);
     408             :     }
     409             : 
     410           1 :     ScFormulaCell* pCell = rDoc.GetFormulaCell(ScAddress(1,18,0));
     411           1 :     CPPUNIT_ASSERT_MESSAGE("This should be a formula cell.", pCell);
     412           2 :     ScFormulaCellGroupRef xGroup = pCell->GetCellGroup();
     413           1 :     CPPUNIT_ASSERT_MESSAGE("This cell should be a part of a cell group.", xGroup);
     414           1 :     CPPUNIT_ASSERT_MESSAGE("Incorrect group geometry.", xGroup->mpTopCell->aPos.Row() == 1 && xGroup->mnLength == 18);
     415             : 
     416           2 :     xDocSh->DoClose();
     417           1 : }
     418             : 
     419           1 : void ScFiltersTest::testSheetNamesXLSX()
     420             : {
     421           1 :     ScDocShellRef xDocSh = loadDoc("sheet-names.", XLSX);
     422           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     423             : 
     424           2 :     std::vector<OUString> aTabNames = rDoc.GetAllTableNames();
     425           1 :     CPPUNIT_ASSERT_MESSAGE("The document should have 5 sheets in total.", aTabNames.size() == 5);
     426           1 :     CPPUNIT_ASSERT_EQUAL(OUString("S&P"), aTabNames[0]);
     427           1 :     CPPUNIT_ASSERT_EQUAL(OUString("Sam's Club"), aTabNames[1]);
     428           1 :     CPPUNIT_ASSERT_EQUAL(OUString("\"The Sheet\""), aTabNames[2]);
     429           1 :     CPPUNIT_ASSERT_EQUAL(OUString("A<B"), aTabNames[3]);
     430           1 :     CPPUNIT_ASSERT_EQUAL(OUString("C>D"), aTabNames[4]);
     431             : 
     432           2 :     xDocSh->DoClose();
     433           1 : }
     434             : 
     435           5 : void impl_testLegacyCellAnchoredRotatedShape( ScDocument& rDoc, Rectangle& aRect, ScDrawObjData& aAnchor, long TOLERANCE = 30 /* 30 hmm */ )
     436             : {
     437           5 :     ScDrawLayer* pDrawLayer = rDoc.GetDrawLayer();
     438           5 :     CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer);
     439           5 :     SdrPage* pPage = pDrawLayer->GetPage(0);
     440           5 :     CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage);
     441           5 :     CPPUNIT_ASSERT_EQUAL( static_cast<size_t>(1), pPage->GetObjCount() );
     442             : 
     443           5 :     SdrObject* pObj = pPage->GetObj(0);
     444           5 :     const Rectangle& aSnap = pObj->GetSnapRect();
     445           5 :     printf("expected height %ld actual %ld\n", aRect.GetHeight(), aSnap.GetHeight() );
     446           5 :     CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.GetHeight(), aSnap.GetHeight(), TOLERANCE ) );
     447           5 :     printf("expected width %ld actual %ld\n", aRect.GetWidth(), aSnap.GetWidth() );
     448           5 :     CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.GetWidth(), aSnap.GetWidth(), TOLERANCE ) );
     449           5 :     printf("expected left %ld actual %ld\n", aRect.Left(), aSnap.Left() );
     450           5 :     CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.Left(), aSnap.Left(), TOLERANCE ) );
     451           5 :     printf("expected right %ld actual %ld\n", aRect.Top(), aSnap.Top() );
     452           5 :     CPPUNIT_ASSERT_EQUAL( true, testEqualsWithTolerance( aRect.Top(), aSnap.Top(), TOLERANCE ) );
     453             : 
     454           5 :     ScDrawObjData* pData = ScDrawLayer::GetObjData( pObj );
     455           5 :     CPPUNIT_ASSERT_MESSAGE("expected object meta data", pData);
     456           5 :     printf("expected startrow %" SAL_PRIdINT32 " actual %" SAL_PRIdINT32 "\n", aAnchor.maStart.Row(), pData->maStart.Row()  );
     457           5 :     CPPUNIT_ASSERT_EQUAL( aAnchor.maStart.Row(), pData->maStart.Row() );
     458           5 :     printf("expected startcol %d actual %d\n", aAnchor.maStart.Col(), pData->maStart.Col()  );
     459           5 :     CPPUNIT_ASSERT_EQUAL( aAnchor.maStart.Col(), pData->maStart.Col() );
     460           5 :     printf("expected endrow %" SAL_PRIdINT32 " actual %" SAL_PRIdINT32 "\n", aAnchor.maEnd.Row(), pData->maEnd.Row()  );
     461           5 :     CPPUNIT_ASSERT_EQUAL( aAnchor.maEnd.Row(), pData->maEnd.Row() );
     462           5 :     printf("expected endcol %d actual %d\n", aAnchor.maEnd.Col(), pData->maEnd.Col()  );
     463           5 :     CPPUNIT_ASSERT_EQUAL( aAnchor.maEnd.Col(), pData->maEnd.Col() );
     464           5 : }
     465             : 
     466           1 : void ScFiltersTest::testLegacyCellAnchoredRotatedShape()
     467             : {
     468             :     {
     469             :         // This example doc contains cell anchored shape that is rotated, the
     470             :         // rotated shape is in fact cliped by the sheet boundries ( and thus
     471             :         // is a good edge case test to see if we import it still correctly )
     472           1 :         ScDocShellRef xDocSh = loadDoc("legacycellanchoredrotatedclippedshape.", ODS);
     473             : 
     474           1 :         ScDocument& rDoc = xDocSh->GetDocument();
     475           1 :         CPPUNIT_ASSERT(&rDoc);
     476             :         // ensure the imported legacy rotated shape is in the expected position
     477           1 :         Rectangle aRect( 6000, -2000, 8000, 4000 );
     478             :         // ensure the imported ( and converted ) anchor ( note we internally now store the anchor in
     479             :         // terms of the rotated shape ) is more or less contains the correct info
     480           2 :         ScDrawObjData aAnchor;
     481           1 :         aAnchor.maStart.SetRow( 0 );
     482           1 :         aAnchor.maStart.SetCol( 5 );
     483           1 :         aAnchor.maEnd.SetRow( 3 );
     484           1 :         aAnchor.maEnd.SetCol( 7 );
     485           1 :         impl_testLegacyCellAnchoredRotatedShape( rDoc, aRect, aAnchor );
     486             :         // test save and reload
     487             :         // for some reason having this test in subsequent_export-test.cxx causes
     488             :         // a core dump in editeng ( so moved to here )
     489           1 :         xDocSh = saveAndReload( &(*xDocSh), ODS);
     490           1 :         ScDocument& rDoc2 = xDocSh->GetDocument();
     491           1 :         CPPUNIT_ASSERT(&rDoc2);
     492           1 :         impl_testLegacyCellAnchoredRotatedShape( rDoc2, aRect, aAnchor );
     493             : 
     494           2 :         xDocSh->DoClose();
     495             :     }
     496             :     {
     497             :         // This example doc contains cell anchored shape that is rotated, the
     498             :         // rotated shape is in fact clipped by the sheet boundries, additionally
     499             :         // the shape is completely hidden because the rows the shape occupies
     500             :         // are hidden
     501           1 :         ScDocShellRef xDocSh = loadDoc("legacycellanchoredrotatedhiddenshape.", ODS, true);
     502           1 :         ScDocument& rDoc = xDocSh->GetDocument();
     503           1 :         CPPUNIT_ASSERT(&rDoc);
     504             :         // ensure the imported legacy rotated shape is in the expected position
     505             :         // when a shape is fully hidden reloading seems to result is in some errors, usually
     506             :         // ( same but different error happens pre-patch ) - we should do better here, I regard it
     507             :         // as a pre-existing bug though (#FIXME)
     508             :         //Rectangle aRect( 6000, -2000, 8000, 4000 ); // proper dimensions
     509           1 :         Rectangle aRect( 6000, -2000, 7430, 4000 );
     510             :         // ensure the imported (and converted) anchor (note we internally now store the anchor in
     511             :         // terms of the rotated shape) is more or less contains the correct info
     512           2 :         ScDrawObjData aAnchor;
     513           1 :         aAnchor.maStart.SetRow( 0 );
     514           1 :         aAnchor.maStart.SetCol( 5 );
     515           1 :         aAnchor.maEnd.SetRow( 3 );
     516           1 :         aAnchor.maEnd.SetCol( 7 );
     517           1 :         rDoc.ShowRows(0, 9, 0, true); // show relavent rows
     518           1 :         rDoc.SetDrawPageSize(0); // trigger recalcpos
     519             : 
     520             :         // apply hefty (1 mm) tolerance here, as some opensuse tinderbox
     521             :         // failing
     522           1 :         impl_testLegacyCellAnchoredRotatedShape( rDoc, aRect, aAnchor, 100 );
     523             : 
     524           2 :         xDocSh->DoClose();
     525             :     }
     526             :     {
     527             :         // This example doc contains cell anchored shape that is rotated
     528           1 :         ScDocShellRef xDocSh = loadDoc("legacycellanchoredrotatedshape.", ODS);
     529             : 
     530           1 :         ScDocument& rDoc = xDocSh->GetDocument();
     531           1 :         CPPUNIT_ASSERT(&rDoc);
     532             :         // ensure the imported legacy rotated shape is in the expected position
     533           1 :         Rectangle aRect( 6000, 3000, 8000, 9000 );
     534             :         // ensure the imported (and converted) anchor (note we internally now store the anchor in
     535             :         // terms of the rotated shape) more or less contains the correct info
     536             : 
     537           2 :         ScDrawObjData aAnchor;
     538           1 :         aAnchor.maStart.SetRow( 3 );
     539           1 :         aAnchor.maStart.SetCol( 6 );
     540           1 :         aAnchor.maEnd.SetRow( 9 );
     541           1 :         aAnchor.maEnd.SetCol( 7 );
     542             :         // test import
     543           1 :         impl_testLegacyCellAnchoredRotatedShape( rDoc, aRect, aAnchor );
     544             :         // test save and reload
     545           1 :         xDocSh = saveAndReload( &(*xDocSh), ODS);
     546           1 :         ScDocument& rDoc2 = xDocSh->GetDocument();
     547           1 :         CPPUNIT_ASSERT(&rDoc2);
     548           1 :         impl_testLegacyCellAnchoredRotatedShape( rDoc2, aRect, aAnchor );
     549             : 
     550           2 :         xDocSh->DoClose();
     551             :     }
     552           1 : }
     553             : 
     554           2 : void testEnhancedProtectionImpl( ScDocument& rDoc )
     555             : {
     556           2 :     const ScTableProtection* pProt = rDoc.GetTabProtection(0);
     557             : 
     558           2 :     CPPUNIT_ASSERT( pProt);
     559             : 
     560           2 :     CPPUNIT_ASSERT( !pProt->isBlockEditable( ScRange( 0, 0, 0, 0, 0, 0)));  // locked
     561           2 :     CPPUNIT_ASSERT(  pProt->isBlockEditable( ScRange( 0, 1, 0, 0, 1, 0)));  // editable without password
     562           2 :     CPPUNIT_ASSERT(  pProt->isBlockEditable( ScRange( 0, 2, 0, 0, 2, 0)));  // editable without password
     563           2 :     CPPUNIT_ASSERT( !pProt->isBlockEditable( ScRange( 0, 3, 0, 0, 3, 0)));  // editable with password "foo"
     564           2 :     CPPUNIT_ASSERT( !pProt->isBlockEditable( ScRange( 0, 4, 0, 0, 4, 0)));  // editable with descriptor
     565           2 :     CPPUNIT_ASSERT( !pProt->isBlockEditable( ScRange( 0, 5, 0, 0, 5, 0)));  // editable with descriptor and password "foo"
     566           2 :     CPPUNIT_ASSERT(  pProt->isBlockEditable( ScRange( 0, 1, 0, 0, 2, 0)));  // union of two different editables
     567           2 :     CPPUNIT_ASSERT( !pProt->isBlockEditable( ScRange( 0, 0, 0, 0, 1, 0)));  // union of locked and editable
     568           2 :     CPPUNIT_ASSERT( !pProt->isBlockEditable( ScRange( 0, 2, 0, 0, 3, 0)));  // union of editable and password editable
     569           2 : }
     570             : 
     571           1 : void ScFiltersTest::testEnhancedProtectionXLS()
     572             : {
     573           1 :     ScDocShellRef xDocSh = loadDoc("enhanced-protection.", XLS);
     574           1 :     CPPUNIT_ASSERT(xDocSh.Is());
     575           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     576             : 
     577           1 :     testEnhancedProtectionImpl( rDoc);
     578             : 
     579           1 :     xDocSh->DoClose();
     580           1 : }
     581             : 
     582           1 : void ScFiltersTest::testEnhancedProtectionXLSX()
     583             : {
     584           1 :     ScDocShellRef xDocSh = loadDoc("enhanced-protection.", XLSX);
     585           1 :     CPPUNIT_ASSERT(xDocSh.Is());
     586           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     587             : 
     588           1 :     testEnhancedProtectionImpl( rDoc);
     589             : 
     590           1 :     xDocSh->DoClose();
     591           1 : }
     592             : 
     593           1 : void ScFiltersTest::testSortWithSharedFormulasODS()
     594             : {
     595           1 :     ScDocShellRef xDocSh = loadDoc("shared-formula/sort-crash.", ODS, true);
     596           1 :     CPPUNIT_ASSERT(xDocSh.Is());
     597           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     598             : 
     599             :     // E2:E10 should be shared.
     600           1 :     const ScFormulaCell* pFC = rDoc.GetFormulaCell(ScAddress(4,1,0));
     601           1 :     CPPUNIT_ASSERT(pFC);
     602           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     603           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(9), pFC->GetSharedLength());
     604             : 
     605             :     // E12:E17 should be shared.
     606           1 :     pFC = rDoc.GetFormulaCell(ScAddress(4,11,0));
     607           1 :     CPPUNIT_ASSERT(pFC);
     608           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(11), pFC->GetSharedTopRow());
     609           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), pFC->GetSharedLength());
     610             : 
     611             :     // Set A1:E17 as an anonymous database range to sheet, or else Calc would
     612             :     // refuse to sort the range.
     613           1 :     ScDBData* pDBData = new ScDBData(STR_DB_LOCAL_NONAME, 0, 0, 0, 4, 16, true, true);
     614           1 :     rDoc.SetAnonymousDBData(0, pDBData);
     615             : 
     616             :     // Sort ascending by Column E.
     617             : 
     618           2 :     ScSortParam aSortData;
     619           1 :     aSortData.nCol1 = 0;
     620           1 :     aSortData.nCol2 = 4;
     621           1 :     aSortData.nRow1 = 0;
     622           1 :     aSortData.nRow2 = 16;
     623           1 :     aSortData.bHasHeader = true;
     624           1 :     aSortData.maKeyState[0].bDoSort = true;
     625           1 :     aSortData.maKeyState[0].nField = 4;
     626           1 :     aSortData.maKeyState[0].bAscending = true;
     627             : 
     628             :     // Do the sorting.  This should not crash.
     629           2 :     ScDBDocFunc aFunc(*xDocSh);
     630           1 :     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     631           1 :     CPPUNIT_ASSERT(bSorted);
     632             : 
     633             :     // After the sort, E2:E16 should be shared.
     634           1 :     pFC = rDoc.GetFormulaCell(ScAddress(4,1,0));
     635           1 :     CPPUNIT_ASSERT(pFC);
     636           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), pFC->GetSharedTopRow());
     637           1 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(15), pFC->GetSharedLength());
     638             : 
     639           2 :     xDocSh->DoClose();
     640           1 : }
     641             : 
     642             : // https://bugs.freedesktop.org/attachment.cgi?id=100089 from fdo#77018
     643             : // mentioned also in fdo#79441
     644             : // Document contains cached external references.
     645           1 : void ScFiltersTest::testSortWithSheetExternalReferencesODS()
     646             : {
     647           1 :     ScDocShellRef xDocSh = loadDoc("sort-with-sheet-external-references.", ODS, true);
     648           1 :     CPPUNIT_ASSERT(xDocSh.Is());
     649           1 :     ScDocument& rDoc = xDocSh->GetDocument();
     650           2 :     sc::AutoCalcSwitch aACSwitch(rDoc, true); // turn auto calc on.
     651           1 :     rDoc.CalcAll();
     652             : 
     653             :     // We reset the SortRefUpdate value back to the original in tearDown().
     654           2 :     ScInputOptions aInputOption = SC_MOD()->GetInputOptions();
     655             : 
     656             :     // The complete relative test only works with UpdateReferenceOnSort==true,
     657             :     // but the internal and external sheet references have to work in both
     658             :     // modes.
     659             : 
     660           1 :     aInputOption.SetSortRefUpdate(true);
     661           1 :     SC_MOD()->SetInputOptions(aInputOption);
     662             : 
     663             :     // Sort A15:D20 with relative row references. UpdateReferenceOnSort==true
     664             :     // With in-sheet relative references.
     665           1 :     testSortWithSheetExternalReferencesODS_Impl( xDocSh, 14, 19, true);
     666             : 
     667             :     // Undo sort with relative references to perform same sort.
     668           1 :     rDoc.GetUndoManager()->Undo();
     669           1 :     rDoc.CalcAll();
     670             : 
     671           1 :     aInputOption.SetSortRefUpdate(false);
     672           1 :     SC_MOD()->SetInputOptions(aInputOption);
     673             : 
     674             :     // Sort A15:D20 with relative row references. UpdateReferenceOnSort==false
     675             :     // Without in-sheet relative references.
     676           1 :     testSortWithSheetExternalReferencesODS_Impl( xDocSh, 14, 19, false);
     677             : 
     678             :     // Undo sort with relative references to perform new sort.
     679           1 :     rDoc.GetUndoManager()->Undo();
     680           1 :     rDoc.CalcAll();
     681             : 
     682             :     // Sort with absolute references has to work in both UpdateReferenceOnSort
     683             :     // modes.
     684             : 
     685           1 :     aInputOption.SetSortRefUpdate(true);
     686           1 :     SC_MOD()->SetInputOptions(aInputOption);
     687             : 
     688             :     // Sort A23:D28 with absolute row references. UpdateReferenceOnSort==true
     689             :     // With in-sheet relative references.
     690           1 :     testSortWithSheetExternalReferencesODS_Impl( xDocSh, 22, 27, true);
     691             : 
     692             :     // Undo sort with absolute references to perform same sort.
     693           1 :     rDoc.GetUndoManager()->Undo();
     694           1 :     rDoc.CalcAll();
     695             : 
     696           1 :     aInputOption.SetSortRefUpdate(false);
     697           1 :     SC_MOD()->SetInputOptions(aInputOption);
     698             : 
     699             :     // Sort A23:D28 with absolute row references. UpdateReferenceOnSort==false
     700             :     // With in-sheet relative references.
     701           1 :     testSortWithSheetExternalReferencesODS_Impl( xDocSh, 22, 27, true);
     702             : 
     703           2 :     xDocSh->DoClose();
     704           1 : }
     705             : 
     706           4 : void ScFiltersTest::testSortWithSheetExternalReferencesODS_Impl( ScDocShellRef xDocSh, SCROW nRow1, SCROW nRow2,
     707             :         bool bCheckRelativeInSheet )
     708             : {
     709           4 :     ScDocument& rDoc = xDocSh->GetDocument();
     710             : 
     711             :     // Check the original data is there.
     712          24 :     for (SCROW nRow=nRow1+1; nRow <= nRow2; ++nRow)
     713             :     {
     714          20 :         double aCheck[] = { 1, 2, 3, 4, 5 };
     715          20 :         CPPUNIT_ASSERT_EQUAL( aCheck[nRow-nRow1-1], rDoc.GetValue( ScAddress(0,nRow,0)));
     716             :     }
     717          24 :     for (SCROW nRow=nRow1+1; nRow <= nRow2; ++nRow)
     718             :     {
     719          80 :         for (SCCOL nCol=1; nCol <= 3; ++nCol)
     720             :         {
     721          60 :             double aCheck[] = { 1, 12, 123, 1234, 12345 };
     722          60 :             CPPUNIT_ASSERT_EQUAL( aCheck[nRow-nRow1-1], rDoc.GetValue( ScAddress(nCol,nRow,0)));
     723             :         }
     724             :     }
     725             : 
     726             :     // Set as an anonymous database range to sort.
     727           4 :     ScDBData* pDBData = new ScDBData(STR_DB_LOCAL_NONAME, 0, 0, nRow1, 3, nRow2, true, true);
     728           4 :     rDoc.SetAnonymousDBData(0, pDBData);
     729             : 
     730             :     // Sort descending by Column A.
     731           4 :     ScSortParam aSortData;
     732           4 :     aSortData.nCol1 = 0;
     733           4 :     aSortData.nCol2 = 3;
     734           4 :     aSortData.nRow1 = nRow1;
     735           4 :     aSortData.nRow2 = nRow2;
     736           4 :     aSortData.bHasHeader = true;
     737           4 :     aSortData.maKeyState[0].bDoSort = true;
     738           4 :     aSortData.maKeyState[0].nField = 0;
     739           4 :     aSortData.maKeyState[0].bAscending = false;
     740             : 
     741             :     // Do the sorting.
     742           8 :     ScDBDocFunc aFunc(*xDocSh);
     743           4 :     bool bSorted = aFunc.Sort(0, aSortData, true, true, true);
     744           4 :     CPPUNIT_ASSERT(bSorted);
     745           4 :     rDoc.CalcAll();
     746             : 
     747             :     // Check the sort and that all sheet references and external references are
     748             :     // adjusted to point to the original location.
     749          24 :     for (SCROW nRow=nRow1+1; nRow <= nRow2; ++nRow)
     750             :     {
     751          20 :         double aCheck[] = { 5, 4, 3, 2, 1 };
     752          20 :         CPPUNIT_ASSERT_EQUAL( aCheck[nRow-nRow1-1], rDoc.GetValue( ScAddress(0,nRow,0)));
     753             :     }
     754             :     // The last column (D) are in-sheet relative references.
     755           4 :     SCCOL nEndCol = (bCheckRelativeInSheet ? 3 : 2);
     756          24 :     for (SCROW nRow=nRow1+1; nRow <= nRow2; ++nRow)
     757             :     {
     758          75 :         for (SCCOL nCol=1; nCol <= nEndCol; ++nCol)
     759             :         {
     760          55 :             double aCheck[] = { 12345, 1234, 123, 12, 1 };
     761          55 :             CPPUNIT_ASSERT_EQUAL( aCheck[nRow-nRow1-1], rDoc.GetValue( ScAddress(nCol,nRow,0)));
     762             :         }
     763           4 :     }
     764           4 : }
     765             : 
     766          17 : ScFiltersTest::ScFiltersTest()
     767             :     : ScBootstrapFixture( "/sc/qa/unit/data" )
     768          17 :     , mbUpdateReferenceOnSort(false)
     769             : {
     770          17 : }
     771             : 
     772          17 : void ScFiltersTest::setUp()
     773             : {
     774          17 :     test::BootstrapFixture::setUp();
     775             : 
     776             :     // This is a bit of a fudge, we do this to ensure that ScGlobals::ensure,
     777             :     // which is a private symbol to us, gets called
     778          34 :     m_xCalcComponent =
     779          51 :         getMultiServiceFactory()->createInstance("com.sun.star.comp.Calc.SpreadsheetDocument");
     780          17 :     CPPUNIT_ASSERT_MESSAGE("no calc component!", m_xCalcComponent.is());
     781             : 
     782             :     // one test sets this configuration option; make sure we remember the
     783             :     // original value
     784          17 :     ScInputOptions aInputOption = SC_MOD()->GetInputOptions();
     785          17 :     mbUpdateReferenceOnSort = aInputOption.GetSortRefUpdate();
     786          17 : }
     787             : 
     788          17 : void ScFiltersTest::tearDown()
     789             : {
     790          17 :     uno::Reference< lang::XComponent >( m_xCalcComponent, UNO_QUERY_THROW )->dispose();
     791          17 :     test::BootstrapFixture::tearDown();
     792             : 
     793             :     // one test sets this configuration option; make sure we return it back
     794          17 :     ScInputOptions aInputOption = SC_MOD()->GetInputOptions();
     795          17 :     if (mbUpdateReferenceOnSort != aInputOption.GetSortRefUpdate())
     796             :     {
     797           0 :         aInputOption.SetSortRefUpdate(mbUpdateReferenceOnSort);
     798           0 :         SC_MOD()->SetInputOptions(aInputOption);
     799          17 :     }
     800          17 : }
     801             : 
     802           1 : CPPUNIT_TEST_SUITE_REGISTRATION(ScFiltersTest);
     803             : 
     804           4 : CPPUNIT_PLUGIN_IMPLEMENT();
     805             : 
     806             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.11