LCOV - code coverage report
Current view: top level - sc/qa/unit - ucalc.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 2402 2419 99.3 %
Date: 2012-08-25 Functions: 97 98 99.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 6289 12649 49.7 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * Version: MPL 1.1 / GPLv3+ / LGPLv3+
       4                 :            :  *
       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. You may obtain a copy of the License at
       8                 :            :  * http://www.mozilla.org/MPL/
       9                 :            :  *
      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.
      14                 :            :  *
      15                 :            :  * The Initial Developer of the Original Code is
      16                 :            :  *       Novell, Inc.
      17                 :            :  * Portions created by the Initial Developer are Copyright (C) 2010 the
      18                 :            :  * Initial Developer. All Rights Reserved.
      19                 :            :  *
      20                 :            :  * Contributor(s):  Michael Meeks <michael.meeks@novell.com>
      21                 :            :  *                  Kohei Yoshida <kyoshida@novell.com>
      22                 :            :  *
      23                 :            :  * Alternatively, the contents of this file may be used under the terms of
      24                 :            :  * either the GNU General Public License Version 3 or later (the "GPLv3+"), or
      25                 :            :  * the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
      26                 :            :  * in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
      27                 :            :  * instead of those above.
      28                 :            :  */
      29                 :            : #include <sal/config.h>
      30                 :            : #include <test/bootstrapfixture.hxx>
      31                 :            : 
      32                 :            : #include <rtl/strbuf.hxx>
      33                 :            : #include <osl/file.hxx>
      34                 :            : 
      35                 :            : #include "scdll.hxx"
      36                 :            : #include "document.hxx"
      37                 :            : #include "stringutil.hxx"
      38                 :            : #include "scmatrix.hxx"
      39                 :            : #include "drwlayer.hxx"
      40                 :            : #include "scitems.hxx"
      41                 :            : #include "reffind.hxx"
      42                 :            : #include "markdata.hxx"
      43                 :            : #include "clipparam.hxx"
      44                 :            : #include "refundo.hxx"
      45                 :            : #include "undoblk.hxx"
      46                 :            : #include "undotab.hxx"
      47                 :            : #include "queryentry.hxx"
      48                 :            : #include "postit.hxx"
      49                 :            : #include "attrib.hxx"
      50                 :            : #include "dbdata.hxx"
      51                 :            : #include "reftokenhelper.hxx"
      52                 :            : #include "userdat.hxx"
      53                 :            : 
      54                 :            : #include "docsh.hxx"
      55                 :            : #include "docfunc.hxx"
      56                 :            : #include "dbdocfun.hxx"
      57                 :            : #include "funcdesc.hxx"
      58                 :            : #include "externalrefmgr.hxx"
      59                 :            : 
      60                 :            : #include "dpshttab.hxx"
      61                 :            : #include "dpobject.hxx"
      62                 :            : #include "dpsave.hxx"
      63                 :            : #include "dpdimsave.hxx"
      64                 :            : #include "dpcache.hxx"
      65                 :            : #include "calcconfig.hxx"
      66                 :            : #include "interpre.hxx"
      67                 :            : 
      68                 :            : #include "formula/IFunctionDescription.hxx"
      69                 :            : 
      70                 :            : #include <basegfx/polygon/b2dpolygon.hxx>
      71                 :            : #include <editeng/boxitem.hxx>
      72                 :            : 
      73                 :            : #include <svx/svdograf.hxx>
      74                 :            : #include <svx/svdpage.hxx>
      75                 :            : #include <svx/svdocirc.hxx>
      76                 :            : #include <svx/svdopath.hxx>
      77                 :            : 
      78                 :            : #include <sfx2/docfile.hxx>
      79                 :            : 
      80                 :            : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
      81                 :            : #include <com/sun/star/sheet/DataPilotFieldGroupBy.hpp>
      82                 :            : #include <com/sun/star/sheet/GeneralFunction.hpp>
      83                 :            : 
      84                 :            : #include <ucbhelper/contentbroker.hxx>
      85                 :            : 
      86                 :            : #include <iostream>
      87                 :            : #include <vector>
      88                 :            : 
      89                 :            : #define CALC_DEBUG_OUTPUT 0
      90                 :            : 
      91                 :            : #include "helper/debughelper.hxx"
      92                 :            : 
      93                 :            : const int indeterminate = 2;
      94                 :            : 
      95                 :            : using namespace ::com::sun::star;
      96                 :            : using ::rtl::OUString;
      97                 :            : using ::rtl::OUStringBuffer;
      98                 :            : using ::std::cout;
      99                 :            : using ::std::cerr;
     100                 :            : using ::std::endl;
     101                 :            : using ::std::vector;
     102                 :            : 
     103                 :            : namespace {
     104                 :            : 
     105 [ +  - ][ -  + ]:        270 : class Test : public test::BootstrapFixture {
     106                 :            : public:
     107                 :            :     Test();
     108                 :            : 
     109                 :            :     virtual void setUp();
     110                 :            :     virtual void tearDown();
     111                 :            : 
     112                 :            :     void testCollator();
     113                 :            :     void testInput();
     114                 :            :     void testCellFunctions();
     115                 :            : 
     116                 :            :     /**
     117                 :            :      * Make sure the SHEETS function gets properly updated during sheet
     118                 :            :      * insertion and removal.
     119                 :            :      */
     120                 :            :     void testSheetsFunc();
     121                 :            :     void testVolatileFunc();
     122                 :            :     void testFuncParam();
     123                 :            :     void testNamedRange();
     124                 :            :     void testCSV();
     125                 :            :     void testMatrix();
     126                 :            : 
     127                 :            :     /**
     128                 :            :      * Basic test for pivot tables.
     129                 :            :      */
     130                 :            :     void testPivotTable();
     131                 :            : 
     132                 :            :     /**
     133                 :            :      * Test against unwanted automatic format detection on field names and
     134                 :            :      * field members in pivot tables.
     135                 :            :      */
     136                 :            :     void testPivotTableLabels();
     137                 :            : 
     138                 :            :     /**
     139                 :            :      * Make sure that we set cells displaying date values numeric cells,
     140                 :            :      * rather than text cells.  Grouping by date or number functionality
     141                 :            :      * depends on this.
     142                 :            :      */
     143                 :            :     void testPivotTableDateLabels();
     144                 :            : 
     145                 :            :     /**
     146                 :            :      * Test for pivot table's filtering functionality by page fields.
     147                 :            :      */
     148                 :            :     void testPivotTableFilters();
     149                 :            : 
     150                 :            :     /**
     151                 :            :      * Test for pivot table's named source range.
     152                 :            :      */
     153                 :            :     void testPivotTableNamedSource();
     154                 :            : 
     155                 :            :     /**
     156                 :            :      * Test for pivot table cache.  Each dimension in the pivot cache stores
     157                 :            :      * only unique values that are sorted in ascending order.
     158                 :            :      */
     159                 :            :     void testPivotTableCache();
     160                 :            : 
     161                 :            :     /**
     162                 :            :      * Test for pivot table containing data fields that reference the same
     163                 :            :      * source field but different functions.
     164                 :            :      */
     165                 :            :     void testPivotTableDuplicateDataFields();
     166                 :            : 
     167                 :            :     void testPivotTableNormalGrouping();
     168                 :            :     void testPivotTableNumberGrouping();
     169                 :            :     void testPivotTableDateGrouping();
     170                 :            :     void testPivotTableEmptyRows();
     171                 :            :     void testPivotTableTextNumber();
     172                 :            : 
     173                 :            :     /**
     174                 :            :      * Test for checking that pivot table treats strings in a case insensitive
     175                 :            :      * manner.
     176                 :            :      */
     177                 :            :     void testPivotTableCaseInsensitiveStrings();
     178                 :            : 
     179                 :            :     void testSheetCopy();
     180                 :            :     void testSheetMove();
     181                 :            :     void testExternalRef();
     182                 :            :     void testExternalRefFunctions();
     183                 :            :     void testDataArea();
     184                 :            :     void testAutofilter();
     185                 :            :     void testCopyPaste();
     186                 :            :     void testMergedCells();
     187                 :            :     void testUpdateReference();
     188                 :            : 
     189                 :            :     /**
     190                 :            :      * Make sure the sheet streams are invalidated properly.
     191                 :            :      */
     192                 :            :     void testStreamValid();
     193                 :            : 
     194                 :            :     /**
     195                 :            :      * Test built-in cell functions to make sure their categories and order
     196                 :            :      * are correct.
     197                 :            :      */
     198                 :            :     void testFunctionLists();
     199                 :            : 
     200                 :            :     void testGraphicsInGroup();
     201                 :            :     void testGraphicsOnSheetMove();
     202                 :            : 
     203                 :            :     void testPostIts();
     204                 :            : 
     205                 :            :     /**
     206                 :            :      * Test toggling relative/absolute flag of cell and cell range references.
     207                 :            :      * This corresponds with hitting Shift-F4 while the cursor is on a formula
     208                 :            :      * cell.
     209                 :            :      */
     210                 :            :     void testToggleRefFlag();
     211                 :            : 
     212                 :            :     /**
     213                 :            :      * Test to make sure correct precedent / dependent cells are obtained when
     214                 :            :      * preparing to jump to them.
     215                 :            :      */
     216                 :            :     void testJumpToPrecedentsDependents();
     217                 :            : 
     218                 :            :     void testSetBackgroundColor();
     219                 :            :     void testRenameTable();
     220                 :            : 
     221                 :            :     void testAutoFill();
     222                 :            :     void testCopyPasteFormulas();
     223                 :            :     void testCopyPasteFormulasExternalDoc();
     224                 :            : 
     225                 :            :     void testFindAreaPosRowDown();
     226                 :            :     void testFindAreaPosColRight();
     227                 :            : 
     228 [ +  - ][ +  - ]:          6 :     CPPUNIT_TEST_SUITE(Test);
         [ +  - ][ +  - ]
                 [ #  # ]
     229 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testCollator);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     230 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testInput);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     231 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testCellFunctions);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     232 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testSheetsFunc);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     233 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testVolatileFunc);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     234 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testFuncParam);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     235 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testNamedRange);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     236 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testCSV);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     237 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testMatrix);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     238 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTable);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     239 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableLabels);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     240 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableDateLabels);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     241 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableFilters);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     242 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableNamedSource);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     243 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableCache);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     244 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableDuplicateDataFields);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     245 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableNormalGrouping);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     246 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableNumberGrouping);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     247 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableDateGrouping);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     248 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableEmptyRows);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     249 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableTextNumber);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     250 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPivotTableCaseInsensitiveStrings);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     251 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testSheetCopy);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     252 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testSheetMove);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     253 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testExternalRef);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     254 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testExternalRefFunctions);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     255 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testDataArea);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     256 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testGraphicsInGroup);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     257 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testGraphicsOnSheetMove);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     258 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testPostIts);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     259 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testStreamValid);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     260 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testFunctionLists);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     261 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testToggleRefFlag);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     262 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testAutofilter);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     263 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testCopyPaste);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     264 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testMergedCells);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     265 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testUpdateReference);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     266 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testJumpToPrecedentsDependents);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     267 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testSetBackgroundColor);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     268 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testRenameTable);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     269 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testAutoFill);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     270 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testCopyPasteFormulas);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     271 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testCopyPasteFormulasExternalDoc);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     272 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testFindAreaPosRowDown);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     273 [ +  - ][ +  - ]:          3 :     CPPUNIT_TEST(testFindAreaPosColRight);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     274 [ +  - ][ +  - ]:          6 :     CPPUNIT_TEST_SUITE_END();
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     275                 :            : 
     276                 :            : private:
     277                 :            :     ScDocument *m_pDoc;
     278                 :            :     ScDocShellRef m_xDocShRef;
     279                 :            : };
     280                 :            : 
     281                 :         36 : void clearRange(ScDocument* pDoc, const ScRange& rRange)
     282                 :            : {
     283         [ +  - ]:         36 :     ScMarkData aMarkData;
     284         [ +  - ]:         36 :     aMarkData.SetMarkArea(rRange);
     285                 :            :     pDoc->DeleteArea(
     286                 :         36 :         rRange.aStart.Col(), rRange.aStart.Row(),
     287 [ +  - ][ +  - ]:         72 :         rRange.aEnd.Col(), rRange.aEnd.Row(), aMarkData, IDF_CONTENTS);
     288                 :         36 : }
     289                 :            : 
     290                 :         63 : void printRange(ScDocument* pDoc, const ScRange& rRange, const char* pCaption)
     291                 :            : {
     292                 :         63 :     SCROW nRow1 = rRange.aStart.Row(), nRow2 = rRange.aEnd.Row();
     293                 :         63 :     SCCOL nCol1 = rRange.aStart.Col(), nCol2 = rRange.aEnd.Col();
     294         [ +  - ]:         63 :     SheetPrinter printer(nRow2 - nRow1 + 1, nCol2 - nCol1 + 1);
     295         [ +  + ]:        651 :     for (SCROW nRow = nRow1; nRow <= nRow2; ++nRow)
     296                 :            :     {
     297         [ +  + ]:       2184 :         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
     298                 :            :         {
     299                 :       1596 :             rtl::OUString aVal;
     300         [ +  - ]:       1596 :             pDoc->GetString(nCol, nRow, rRange.aStart.Tab(), aVal);
     301         [ +  - ]:       1596 :             printer.set(nRow-nRow1, nCol-nCol1, aVal);
     302                 :       1596 :         }
     303                 :            :     }
     304         [ +  - ]:         63 :     printer.print(pCaption);
     305                 :         63 : }
     306                 :            : 
     307                 :            : template<size_t _Size>
     308                 :         30 : ScRange insertRangeData(ScDocument* pDoc, const ScAddress& rPos, const char* aData[][_Size], size_t nRowCount)
     309                 :            : {
     310 [ +  + ][ +  + ]:        117 :     for (size_t i = 0; i < _Size; ++i)
         [ +  + ][ +  + ]
     311                 :            :     {
     312 [ +  + ][ +  + ]:        789 :         for (size_t j = 0; j < nRowCount; ++j)
         [ +  + ][ +  + ]
     313                 :            :         {
     314                 :        702 :             SCCOL nCol = i + rPos.Col();
     315                 :        702 :             SCROW nRow = j + rPos.Row();
     316 [ +  - ][ +  - ]:        702 :             pDoc->SetString(nCol, nRow, rPos.Tab(), OUString(aData[j][i], strlen(aData[j][i]), RTL_TEXTENCODING_UTF8));
         [ +  - ][ +  - ]
     317                 :            :         }
     318                 :            :     }
     319                 :            : 
     320                 :         30 :     ScRange aRange(rPos);
     321                 :         30 :     aRange.aEnd.SetCol(rPos.Col()+_Size-1);
     322                 :         30 :     aRange.aEnd.SetRow(rPos.Row()+nRowCount-1);
     323                 :         30 :     printRange(pDoc, aRange, "Range data content");
     324                 :         30 :     return aRange;
     325                 :            : }
     326                 :            : 
     327                 :        135 : Test::Test()
     328                 :        135 :     : m_pDoc(0)
     329                 :            : {
     330                 :        135 : }
     331                 :            : 
     332                 :        135 : void Test::setUp()
     333                 :            : {
     334                 :        135 :     BootstrapFixture::setUp();
     335                 :            : 
     336                 :        135 :     ScDLL::Init();
     337                 :            :     m_xDocShRef = new ScDocShell(
     338                 :            :         SFXMODEL_STANDARD |
     339                 :            :         SFXMODEL_DISABLE_EMBEDDED_SCRIPTS |
     340         [ +  - ]:        135 :         SFXMODEL_DISABLE_DOCUMENT_RECOVERY);
     341                 :            : 
     342                 :        135 :     m_pDoc = m_xDocShRef->GetDocument();
     343                 :        135 : }
     344                 :            : 
     345                 :        135 : void Test::tearDown()
     346                 :            : {
     347                 :        135 :     m_xDocShRef.Clear();
     348                 :        135 :     BootstrapFixture::tearDown();
     349                 :        135 : }
     350                 :            : 
     351                 :          3 : void Test::testCollator()
     352                 :            : {
     353                 :          3 :     OUString s1("A");
     354                 :          3 :     OUString s2("B");
     355         [ +  - ]:          3 :     CollatorWrapper* p = ScGlobal::GetCollator();
     356         [ +  - ]:          3 :     sal_Int32 nRes = p->compareString(s1, s2);
     357 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("these strings are supposed to be different!", nRes != 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     358                 :          3 : }
     359                 :            : 
     360                 :          3 : void Test::testInput()
     361                 :            : {
     362                 :          3 :     rtl::OUString aTabName("foo");
     363 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     364         [ +  - ]:          3 :                             m_pDoc->InsertTab (0, aTabName));
     365                 :            : 
     366                 :          3 :     OUString numstr("'10.5");
     367                 :          3 :     OUString str("'apple'");
     368                 :          3 :     OUString test;
     369                 :            : 
     370         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, numstr);
     371         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 0, test);
     372                 :          3 :     bool bTest = test == "10.5";
     373 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("String number should have the first apostrophe stripped.", bTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     374         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, str);
     375         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 0, test);
     376                 :          3 :     bTest = test == "'apple'";
     377 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Text content should have retained the first apostrophe.", bTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     378                 :            : 
     379                 :            :     // Customized string handling policy.
     380         [ +  - ]:          3 :     ScSetStringParam aParam;
     381                 :          3 :     aParam.mbDetectNumberFormat = false;
     382                 :          3 :     aParam.meSetTextNumFormat = ScSetStringParam::Always;
     383                 :          3 :     aParam.mbHandleApostrophe = false;
     384         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, "000123", &aParam);
     385         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 0, test);
     386 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Text content should have been treated as string, not number.", test == "000123");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     387                 :            : 
     388         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
     389                 :          3 : }
     390                 :            : 
     391                 :          3 : void testFuncSUM(ScDocument* pDoc)
     392                 :            : {
     393                 :          3 :     double val = 1;
     394                 :            :     double result;
     395         [ +  - ]:          3 :     pDoc->SetValue (0, 0, 0, val);
     396         [ +  - ]:          3 :     pDoc->SetValue (0, 1, 0, val);
     397         [ +  - ]:          3 :     pDoc->SetString (0, 2, 0, rtl::OUString("=SUM(A1:A2)"));
     398         [ +  - ]:          3 :     pDoc->CalcAll();
     399         [ +  - ]:          3 :     pDoc->GetValue (0, 2, 0, result);
     400 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 2.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     401                 :          3 : }
     402                 :            : 
     403                 :          3 : void testFuncPRODUCT(ScDocument* pDoc)
     404                 :            : {
     405                 :          3 :     double val = 1;
     406                 :            :     double result;
     407         [ +  - ]:          3 :     pDoc->SetValue(0, 0, 0, val);
     408                 :          3 :     val = 2;
     409         [ +  - ]:          3 :     pDoc->SetValue(0, 1, 0, val);
     410                 :          3 :     val = 3;
     411         [ +  - ]:          3 :     pDoc->SetValue(0, 2, 0, val);
     412         [ +  - ]:          3 :     pDoc->SetString(0, 3, 0, OUString("=PRODUCT(A1:A3)"));
     413         [ +  - ]:          3 :     pDoc->CalcAll();
     414         [ +  - ]:          3 :     pDoc->GetValue(0, 3, 0, result);
     415 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT failed", result == 6.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     416                 :            : 
     417         [ +  - ]:          3 :     pDoc->SetString(0, 4, 0, OUString("=PRODUCT({1;2;3})"));
     418         [ +  - ]:          3 :     pDoc->CalcAll();
     419         [ +  - ]:          3 :     pDoc->GetValue(0, 4, 0, result);
     420 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Calculation of PRODUCT with inline array failed", result == 6.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     421                 :          3 : }
     422                 :            : 
     423                 :          3 : void testFuncN(ScDocument* pDoc)
     424                 :            : {
     425                 :            :     double result;
     426                 :            : 
     427                 :            :     // Clear the area first.
     428         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 1, 20, 0));
     429                 :            : 
     430                 :            :     // Put values to reference.
     431                 :          3 :     double val = 0;
     432         [ +  - ]:          3 :     pDoc->SetValue(0, 0, 0, val);
     433         [ +  - ]:          3 :     pDoc->SetString(0, 2, 0, OUString("Text"));
     434                 :          3 :     val = 1;
     435         [ +  - ]:          3 :     pDoc->SetValue(0, 3, 0, val);
     436                 :          3 :     val = -1;
     437         [ +  - ]:          3 :     pDoc->SetValue(0, 4, 0, val);
     438                 :          3 :     val = 12.3;
     439         [ +  - ]:          3 :     pDoc->SetValue(0, 5, 0, val);
     440         [ +  - ]:          3 :     pDoc->SetString(0, 6, 0, OUString("'12.3"));
     441                 :            : 
     442                 :            :     // Cell references
     443         [ +  - ]:          3 :     pDoc->SetString(1, 0, 0, OUString("=N(A1)"));
     444         [ +  - ]:          3 :     pDoc->SetString(1, 1, 0, OUString("=N(A2)"));
     445         [ +  - ]:          3 :     pDoc->SetString(1, 2, 0, OUString("=N(A3)"));
     446         [ +  - ]:          3 :     pDoc->SetString(1, 3, 0, OUString("=N(A4)"));
     447         [ +  - ]:          3 :     pDoc->SetString(1, 4, 0, OUString("=N(A5)"));
     448         [ +  - ]:          3 :     pDoc->SetString(1, 5, 0, OUString("=N(A6)"));
     449         [ +  - ]:          3 :     pDoc->SetString(1, 6, 0, OUString("=N(A9)"));
     450                 :            : 
     451                 :            :     // In-line values
     452         [ +  - ]:          3 :     pDoc->SetString(1, 7, 0, OUString("=N(0)"));
     453         [ +  - ]:          3 :     pDoc->SetString(1, 8, 0, OUString("=N(1)"));
     454         [ +  - ]:          3 :     pDoc->SetString(1, 9, 0, OUString("=N(-1)"));
     455         [ +  - ]:          3 :     pDoc->SetString(1, 10, 0, OUString("=N(123)"));
     456         [ +  - ]:          3 :     pDoc->SetString(1, 11, 0, OUString("=N(\"\")"));
     457         [ +  - ]:          3 :     pDoc->SetString(1, 12, 0, OUString("=N(\"12\")"));
     458         [ +  - ]:          3 :     pDoc->SetString(1, 13, 0, OUString("=N(\"foo\")"));
     459                 :            : 
     460                 :            :     // Range references
     461         [ +  - ]:          3 :     pDoc->SetString(2, 2, 0, OUString("=N(A1:A8)"));
     462         [ +  - ]:          3 :     pDoc->SetString(2, 3, 0, OUString("=N(A1:A8)"));
     463         [ +  - ]:          3 :     pDoc->SetString(2, 4, 0, OUString("=N(A1:A8)"));
     464         [ +  - ]:          3 :     pDoc->SetString(2, 5, 0, OUString("=N(A1:A8)"));
     465                 :            : 
     466                 :            :     // Calculate and check the results.
     467         [ +  - ]:          3 :     pDoc->CalcAll();
     468                 :            :     double checks1[] = {
     469                 :            :         0, 0,  0,    1, -1, 12.3, 0, // cell reference
     470                 :            :         0, 1, -1, 123,  0,    0, 0   // in-line values
     471                 :          3 :     };
     472         [ +  + ]:         45 :     for (size_t i = 0; i < SAL_N_ELEMENTS(checks1); ++i)
     473                 :            :     {
     474         [ +  - ]:         42 :         pDoc->GetValue(1, i, 0, result);
     475                 :         42 :         bool bGood = result == checks1[i];
     476         [ -  + ]:         42 :         if (!bGood)
     477                 :            :         {
     478 [ #  # ][ #  # ]:          0 :             cerr << "row " << (i+1) << ": expected=" << checks1[i] << " actual=" << result << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     479 [ #  # ][ #  # ]:          0 :             CPPUNIT_ASSERT_MESSAGE("Unexpected result for N", false);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     480                 :            :         }
     481                 :            :     }
     482                 :            :     double checks2[] = {
     483                 :            :         0, 1, -1, 12.3               // range references
     484                 :          3 :     };
     485         [ +  + ]:         15 :     for (size_t i = 0; i < SAL_N_ELEMENTS(checks2); ++i)
     486                 :            :     {
     487         [ +  - ]:         12 :         pDoc->GetValue(1, i+2, 0, result);
     488                 :         12 :         bool bGood = result == checks2[i];
     489         [ -  + ]:         12 :         if (!bGood)
     490                 :            :         {
     491 [ #  # ][ #  # ]:          0 :             cerr << "row " << (i+2+1) << ": expected=" << checks2[i] << " actual=" << result << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     492 [ #  # ][ #  # ]:          0 :             CPPUNIT_ASSERT_MESSAGE("Unexpected result for N", false);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     493                 :            :         }
     494                 :            :     }
     495                 :          3 : }
     496                 :            : 
     497                 :          3 : void testFuncCOUNTIF(ScDocument* pDoc)
     498                 :            : {
     499                 :            :     // COUNTIF (test case adopted from OOo i#36381)
     500                 :            : 
     501                 :            :     // Empty A1:A39 first.
     502         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 0, 40, 0));
     503                 :            : 
     504                 :            :     // Raw data (rows 1 through 9)
     505                 :            :     const char* aData[] = {
     506                 :            :         "1999",
     507                 :            :         "2000",
     508                 :            :         "0",
     509                 :            :         "0",
     510                 :            :         "0",
     511                 :            :         "2002",
     512                 :            :         "2001",
     513                 :            :         "X",
     514                 :            :         "2002"
     515                 :          3 :     };
     516                 :            : 
     517                 :          3 :     SCROW nRows = SAL_N_ELEMENTS(aData);
     518         [ +  + ]:         30 :     for (SCROW i = 0; i < nRows; ++i)
     519         [ +  - ]:         27 :         pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aData[i]));
     520                 :            : 
     521         [ +  - ]:          3 :     printRange(pDoc, ScRange(0, 0, 0, 0, 8, 0), "data range for COUNTIF");
     522                 :            : 
     523                 :            :     // formulas and results
     524                 :            :     struct {
     525                 :            :         const char* pFormula; double fResult;
     526                 :            :     } aChecks[] = {
     527                 :            :         { "=COUNTIF(A1:A12;1999)",       1 },
     528                 :            :         { "=COUNTIF(A1:A12;2002)",       2 },
     529                 :            :         { "=COUNTIF(A1:A12;1998)",       0 },
     530                 :            :         { "=COUNTIF(A1:A12;\">=1999\")", 5 },
     531                 :            :         { "=COUNTIF(A1:A12;\">1999\")",  4 },
     532                 :            :         { "=COUNTIF(A1:A12;\"<2001\")",  5 },
     533                 :            :         { "=COUNTIF(A1:A12;\">0\")",     5 },
     534                 :            :         { "=COUNTIF(A1:A12;\">=0\")",    8 },
     535                 :            :         { "=COUNTIF(A1:A12;0)",          3 },
     536                 :            :         { "=COUNTIF(A1:A12;\"X\")",      1 },
     537                 :            :         { "=COUNTIF(A1:A12;)",           3 }
     538                 :          3 :     };
     539                 :            : 
     540                 :          3 :     nRows = SAL_N_ELEMENTS(aChecks);
     541         [ +  + ]:         36 :     for (SCROW i = 0; i < nRows; ++i)
     542                 :            :     {
     543                 :         33 :         SCROW nRow = 20 + i;
     544         [ +  - ]:         33 :         pDoc->SetString(0, nRow, 0, rtl::OUString::createFromAscii(aChecks[i].pFormula));
     545                 :            :     }
     546         [ +  - ]:          3 :     pDoc->CalcAll();
     547                 :            : 
     548         [ +  + ]:         36 :     for (SCROW i = 0; i < nRows; ++i)
     549                 :            :     {
     550                 :            :         double result;
     551                 :         33 :         SCROW nRow = 20 + i;
     552         [ +  - ]:         33 :         pDoc->GetValue(0, nRow, 0, result);
     553                 :         33 :         bool bGood = result == aChecks[i].fResult;
     554         [ -  + ]:         33 :         if (!bGood)
     555                 :            :         {
     556 [ #  # ][ #  # ]:          0 :             cerr << "row " << (nRow+1) << ": formula" << aChecks[i].pFormula
         [ #  # ][ #  # ]
     557 [ #  # ][ #  # ]:          0 :                 << "  expected=" << aChecks[i].fResult << "  actual=" << result << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
     558 [ #  # ][ #  # ]:          0 :             CPPUNIT_ASSERT_MESSAGE("Unexpected result for COUNTIF", false);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     559                 :            :         }
     560                 :            :     }
     561                 :            : 
     562                 :            :     // Don't count empty strings when searching for a number.
     563                 :            : 
     564                 :            :     // Clear A1:A2.
     565         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 0, 1, 0));
     566                 :            : 
     567         [ +  - ]:          3 :     pDoc->SetString(0, 0, 0, rtl::OUString("=\"\""));
     568         [ +  - ]:          3 :     pDoc->SetString(0, 1, 0, rtl::OUString("=COUNTIF(A1;1)"));
     569         [ +  - ]:          3 :     pDoc->CalcAll();
     570                 :            : 
     571         [ +  - ]:          3 :     double result = pDoc->GetValue(0, 1, 0);
     572 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("We shouldn't count empty string as valid number.", result == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     573                 :          3 : }
     574                 :            : 
     575                 :          3 : void testFuncVLOOKUP(ScDocument* pDoc)
     576                 :            : {
     577                 :            :     // VLOOKUP
     578                 :            : 
     579                 :            :     // Clear A1:F40.
     580         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 5, 39, 0));
     581                 :            : 
     582                 :            :     // Raw data
     583                 :            :     const char* aData[][2] = {
     584                 :            :         { "Key", "Val" },
     585                 :            :         {  "10",   "3" },
     586                 :            :         {  "20",   "4" },
     587                 :            :         {  "30",   "5" },
     588                 :            :         {  "40",   "6" },
     589                 :            :         {  "50",   "7" },
     590                 :            :         {  "60",   "8" },
     591                 :            :         {  "70",   "9" },
     592                 :            :         {   "B",  "10" },
     593                 :            :         {   "B",  "11" },
     594                 :            :         {   "C",  "12" },
     595                 :            :         {   "D",  "13" },
     596                 :            :         {   "E",  "14" },
     597                 :            :         {   "F",  "15" },
     598                 :            :         { 0, 0 } // terminator
     599                 :          3 :     };
     600                 :            : 
     601                 :            :     // Insert raw data into A1:B14.
     602         [ +  + ]:         45 :     for (SCROW i = 0; aData[i][0]; ++i)
     603                 :            :     {
     604         [ +  - ]:         42 :         pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aData[i][0]));
     605         [ +  - ]:         42 :         pDoc->SetString(1, i, 0, rtl::OUString::createFromAscii(aData[i][1]));
     606                 :            :     }
     607                 :            : 
     608         [ +  - ]:          3 :     printRange(pDoc, ScRange(0, 0, 0, 1, 13, 0), "raw data for VLOOKUP");
     609                 :            : 
     610                 :            :     // Formula data
     611                 :            :     struct {
     612                 :            :         const char* pLookup; const char* pFormula; const char* pRes;
     613                 :            :     } aChecks[] = {
     614                 :            :         { "Lookup",  "Formula", 0 },
     615                 :            :         { "12",      "=VLOOKUP(D2;A2:B14;2;1)",     "3" },
     616                 :            :         { "29",      "=VLOOKUP(D3;A2:B14;2;1)",     "4" },
     617                 :            :         { "31",      "=VLOOKUP(D4;A2:B14;2;1)",     "5" },
     618                 :            :         { "45",      "=VLOOKUP(D5;A2:B14;2;1)",     "6" },
     619                 :            :         { "56",      "=VLOOKUP(D6;A2:B14;2;1)",     "7" },
     620                 :            :         { "65",      "=VLOOKUP(D7;A2:B14;2;1)",     "8" },
     621                 :            :         { "78",      "=VLOOKUP(D8;A2:B14;2;1)",     "9" },
     622                 :            :         { "Andy",    "=VLOOKUP(D9;A2:B14;2;1)",  "#N/A" },
     623                 :            :         { "Bruce",   "=VLOOKUP(D10;A2:B14;2;1)",   "11" },
     624                 :            :         { "Charlie", "=VLOOKUP(D11;A2:B14;2;1)",   "12" },
     625                 :            :         { "David",   "=VLOOKUP(D12;A2:B14;2;1)",   "13" },
     626                 :            :         { "Edward",  "=VLOOKUP(D13;A2:B14;2;1)",   "14" },
     627                 :            :         { "Frank",   "=VLOOKUP(D14;A2:B14;2;1)",   "15" },
     628                 :            :         { "Henry",   "=VLOOKUP(D15;A2:B14;2;1)",   "15" },
     629                 :            :         { "100",     "=VLOOKUP(D16;A2:B14;2;1)",    "9" },
     630                 :            :         { "1000",    "=VLOOKUP(D17;A2:B14;2;1)",    "9" },
     631                 :            :         { "Zena",    "=VLOOKUP(D18;A2:B14;2;1)",   "15" }
     632                 :          3 :     };
     633                 :            : 
     634                 :            :     // Insert formula data into D1:E18.
     635         [ +  + ]:         57 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     636                 :            :     {
     637         [ +  - ]:         54 :         pDoc->SetString(3, i, 0, rtl::OUString::createFromAscii(aChecks[i].pLookup));
     638         [ +  - ]:         54 :         pDoc->SetString(4, i, 0, rtl::OUString::createFromAscii(aChecks[i].pFormula));
     639                 :            :     }
     640         [ +  - ]:          3 :     pDoc->CalcAll();
     641         [ +  - ]:          3 :     printRange(pDoc, ScRange(3, 0, 0, 4, 17, 0), "formula data for VLOOKUP");
     642                 :            : 
     643                 :            :     // Verify results.
     644         [ +  + ]:         57 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     645                 :            :     {
     646         [ +  + ]:         54 :         if (i == 0)
     647                 :            :             // Skip the header row.
     648                 :          3 :             continue;
     649                 :            : 
     650                 :         51 :         rtl::OUString aRes;
     651         [ +  - ]:         51 :         pDoc->GetString(4, i, 0, aRes);
     652                 :         51 :         bool bGood = aRes.equalsAscii(aChecks[i].pRes);
     653         [ -  + ]:         51 :         if (!bGood)
     654                 :            :         {
     655 [ #  # ][ #  # ]:          0 :             cerr << "row " << (i+1) << ": lookup value='" << aChecks[i].pLookup
         [ #  # ][ #  # ]
     656 [ #  # ][ #  # ]:          0 :                 << "'  expected='" << aChecks[i].pRes << "' actual='" << aRes << "'" << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     657 [ #  # ][ #  # ]:          0 :             CPPUNIT_ASSERT_MESSAGE("Unexpected result for VLOOKUP", false);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     658                 :            :         }
     659                 :         51 :     }
     660                 :          3 : }
     661                 :            : 
     662                 :            : struct NumStrCheck {
     663                 :            :     double fVal;
     664                 :            :     const char* pRes;
     665                 :            : };
     666                 :            : 
     667                 :            : struct StrStrCheck {
     668                 :            :     const char* pVal;
     669                 :            :     const char* pRes;
     670                 :            : };
     671                 :            : 
     672                 :            : template<size_t _DataSize, size_t _FormulaSize, int _Type>
     673                 :          6 : void runTestMATCH(ScDocument* pDoc, const char* aData[_DataSize], StrStrCheck aChecks[_FormulaSize])
     674                 :            : {
     675                 :          6 :     size_t nDataSize = _DataSize;
     676 [ +  + ][ +  + ]:         78 :     for (size_t i = 0; i < nDataSize; ++i)
     677 [ +  - ][ +  - ]:         72 :         pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aData[i]));
     678                 :            : 
     679 [ +  + ][ +  + ]:         99 :     for (size_t i = 0; i < _FormulaSize; ++i)
     680                 :            :     {
     681 [ +  - ][ +  - ]:         93 :         pDoc->SetString(1, i, 0, rtl::OUString::createFromAscii(aChecks[i].pVal));
     682                 :            : 
     683                 :         93 :         rtl::OUStringBuffer aBuf;
     684   [ +  -  +  - ]:         93 :         aBuf.appendAscii("=MATCH(B");
     685 [ +  - ][ +  - ]:         93 :         aBuf.append(static_cast<sal_Int32>(i+1));
     686 [ +  - ][ +  - ]:         93 :         aBuf.appendAscii(";A1:A");
     687 [ +  - ][ +  - ]:         93 :         aBuf.append(static_cast<sal_Int32>(nDataSize));
     688 [ +  - ][ +  - ]:         93 :         aBuf.appendAscii(";");
     689 [ +  - ][ +  - ]:         93 :         aBuf.append(static_cast<sal_Int32>(_Type));
     690 [ +  - ][ +  - ]:         93 :         aBuf.appendAscii(")");
     691 [ +  - ][ +  - ]:         93 :         rtl::OUString aFormula = aBuf.makeStringAndClear();
     692 [ +  - ][ +  - ]:         93 :         pDoc->SetString(2, i, 0, aFormula);
     693                 :            :     }
     694                 :            : 
     695                 :          6 :     pDoc->CalcAll();
     696   [ +  -  +  - ]:          6 :     printRange(pDoc, ScRange(0, 0, 0, 2, _FormulaSize-1, 0), "MATCH");
     697                 :            : 
     698                 :            :     // verify the results.
     699 [ +  + ][ +  + ]:         99 :     for (size_t i = 0; i < _FormulaSize; ++i)
     700                 :            :     {
     701                 :         93 :         rtl::OUString aStr;
     702   [ +  -  +  - ]:         93 :         pDoc->GetString(2, i, 0, aStr);
     703 [ -  + ][ -  + ]:         93 :         if (!aStr.equalsAscii(aChecks[i].pRes))
     704                 :            :         {
     705 [ #  # ][ #  # ]:          0 :             cerr << "row " << (i+1) << ": expected='" << aChecks[i].pRes << "' actual='" << aStr << "'"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     706                 :            :                 << " criterion='" << aChecks[i].pVal << "'" << endl;
     707 [ #  # ][ #  # ]:         93 :             CPPUNIT_ASSERT_MESSAGE("Unexpected result for MATCH", false);
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     708                 :            :         }
     709                 :            :     }
     710                 :          6 : }
     711                 :            : 
     712                 :          3 : void testFuncMATCH(ScDocument* pDoc)
     713                 :            : {
     714         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 4, 40, 0));
     715                 :            :     {
     716                 :            :         // Ascending in-exact match
     717                 :            : 
     718                 :            :         // data range (A1:A9)
     719                 :            :         const char* aData[] = {
     720                 :            :             "1",
     721                 :            :             "2",
     722                 :            :             "3",
     723                 :            :             "4",
     724                 :            :             "5",
     725                 :            :             "6",
     726                 :            :             "7",
     727                 :            :             "8",
     728                 :            :             "9",
     729                 :            :             "B",
     730                 :            :             "B",
     731                 :            :             "C",
     732                 :          3 :         };
     733                 :            : 
     734                 :            :         // formula (B1:C12)
     735                 :            :         StrStrCheck aChecks[] = {
     736                 :            :             { "0.8",   "#N/A" },
     737                 :            :             { "1.2",      "1" },
     738                 :            :             { "2.3",      "2" },
     739                 :            :             { "3.9",      "3" },
     740                 :            :             { "4.1",      "4" },
     741                 :            :             { "5.99",     "5" },
     742                 :            :             { "6.1",      "6" },
     743                 :            :             { "7.2",      "7" },
     744                 :            :             { "8.569",    "8" },
     745                 :            :             { "9.59",     "9" },
     746                 :            :             { "10",       "9" },
     747                 :            :             { "100",      "9" },
     748                 :            :             { "Andy",  "#N/A" },
     749                 :            :             { "Bruce",   "11" },
     750                 :            :             { "Charlie", "12" }
     751                 :          3 :         };
     752                 :            : 
     753         [ +  - ]:          3 :         runTestMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),1>(pDoc, aData, aChecks);
     754                 :            :     }
     755                 :            : 
     756                 :            :     {
     757                 :            :         // Descending in-exact match
     758                 :            : 
     759                 :            :         // data range (A1:A9)
     760                 :            :         const char* aData[] = {
     761                 :            :             "D",
     762                 :            :             "C",
     763                 :            :             "B",
     764                 :            :             "9",
     765                 :            :             "8",
     766                 :            :             "7",
     767                 :            :             "6",
     768                 :            :             "5",
     769                 :            :             "4",
     770                 :            :             "3",
     771                 :            :             "2",
     772                 :            :             "1"
     773                 :          3 :         };
     774                 :            : 
     775                 :            :         // formula (B1:C12)
     776                 :            :         StrStrCheck aChecks[] = {
     777                 :            :             { "10",      "#N/A" },
     778                 :            :             { "8.9",     "4" },
     779                 :            :             { "7.8",     "5" },
     780                 :            :             { "6.7",     "6" },
     781                 :            :             { "5.5",     "7" },
     782                 :            :             { "4.6",     "8" },
     783                 :            :             { "3.3",     "9" },
     784                 :            :             { "2.2",     "10" },
     785                 :            :             { "1.1",     "11" },
     786                 :            :             { "0.8",     "12" },
     787                 :            :             { "0",       "12" },
     788                 :            :             { "-2",      "12" },
     789                 :            :             { "Andy",    "3" },
     790                 :            :             { "Bruce",   "2" },
     791                 :            :             { "Charlie", "1" },
     792                 :            :             { "David", "#N/A" }
     793                 :          3 :         };
     794                 :            : 
     795         [ +  - ]:          3 :         runTestMATCH<SAL_N_ELEMENTS(aData),SAL_N_ELEMENTS(aChecks),-1>(pDoc, aData, aChecks);
     796                 :            :     }
     797                 :          3 : }
     798                 :            : 
     799                 :          3 : void testFuncCELL(ScDocument* pDoc)
     800                 :            : {
     801         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 2, 20, 0)); // Clear A1:C21.
     802                 :            : 
     803                 :            :     {
     804                 :          3 :         const char* pContent = "Some random text";
     805         [ +  - ]:          3 :         pDoc->SetString(2, 9, 0, rtl::OUString::createFromAscii(pContent)); // Set this value to C10.
     806                 :          3 :         double val = 1.2;
     807         [ +  - ]:          3 :         pDoc->SetValue(2, 0, 0, val); // Set numeric value to C1;
     808                 :            : 
     809                 :            :         // We don't test: FILENAME, FORMAT, WIDTH, PROTECT, PREFIX
     810                 :            :         StrStrCheck aChecks[] = {
     811                 :            :             { "=CELL(\"COL\";C10)",           "3" },
     812                 :            :             { "=CELL(\"ROW\";C10)",          "10" },
     813                 :            :             { "=CELL(\"SHEET\";C10)",         "1" },
     814                 :            :             { "=CELL(\"ADDRESS\";C10)",   "$C$10" },
     815                 :            :             { "=CELL(\"CONTENTS\";C10)", pContent },
     816                 :            :             { "=CELL(\"COLOR\";C10)",         "0" },
     817                 :            :             { "=CELL(\"TYPE\";C9)",           "b" },
     818                 :            :             { "=CELL(\"TYPE\";C10)",          "l" },
     819                 :            :             { "=CELL(\"TYPE\";C1)",           "v" },
     820                 :            :             { "=CELL(\"PARENTHESES\";C10)",   "0" }
     821                 :          3 :         };
     822                 :            : 
     823         [ +  + ]:         33 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     824         [ +  - ]:         30 :             pDoc->SetString(0, i, 0, rtl::OUString::createFromAscii(aChecks[i].pVal));
     825         [ +  - ]:          3 :         pDoc->CalcAll();
     826                 :            : 
     827         [ +  + ]:         33 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     828                 :            :         {
     829         [ +  - ]:         30 :             rtl::OUString aVal = pDoc->GetString(0, i, 0);
     830 [ +  - ][ +  - ]:         30 :             CPPUNIT_ASSERT_MESSAGE("Unexpected result for CELL", aVal.equalsAscii(aChecks[i].pRes));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     831                 :         30 :         }
     832                 :            :     }
     833                 :          3 : }
     834                 :            : 
     835                 :            : /** See also test case document fdo#44456 sheet cpearson */
     836                 :          3 : void testFuncDATEDIF( ScDocument* pDoc )
     837                 :            : {
     838                 :            :     const char* aData[][5] = {
     839                 :            :         { "2007-01-01", "2007-01-10",  "d",   "9", "=DATEDIF(A1;B1;C1)" } ,
     840                 :            :         { "2007-01-01", "2007-01-31",  "m",   "0", "=DATEDIF(A2;B2;C2)" } ,
     841                 :            :         { "2007-01-01", "2007-02-01",  "m",   "1", "=DATEDIF(A3;B3;C3)" } ,
     842                 :            :         { "2007-01-01", "2007-02-28",  "m",   "1", "=DATEDIF(A4;B4;C4)" } ,
     843                 :            :         { "2007-01-01", "2007-12-31",  "d", "364", "=DATEDIF(A5;B5;C5)" } ,
     844                 :            :         { "2007-01-01", "2007-01-31",  "y",   "0", "=DATEDIF(A6;B6;C6)" } ,
     845                 :            :         { "2007-01-01", "2008-07-01",  "d", "547", "=DATEDIF(A7;B7;C7)" } ,
     846                 :            :         { "2007-01-01", "2008-07-01",  "m",  "18", "=DATEDIF(A8;B8;C8)" } ,
     847                 :            :         { "2007-01-01", "2008-07-01", "ym",   "6", "=DATEDIF(A9;B9;C9)" } ,
     848                 :            :         { "2007-01-01", "2008-07-01", "yd", "182", "=DATEDIF(A10;B10;C10)" } ,
     849                 :            :         { "2008-01-01", "2009-07-01", "yd", "181", "=DATEDIF(A11;B11;C11)" } ,
     850                 :            :         { "2007-01-01", "2007-01-31", "md",  "30", "=DATEDIF(A12;B12;C12)" } ,
     851                 :            :         { "2007-02-01", "2009-03-01", "md",   "0", "=DATEDIF(A13;B13;C13)" } ,
     852                 :            :         { "2008-02-01", "2009-03-01", "md",   "0", "=DATEDIF(A14;B14;C14)" } ,
     853                 :            :         { "2007-01-02", "2007-01-01", "md", "Err:502", "=DATEDIF(A15;B15;C15)" }    // fail date1 > date2
     854                 :          3 :     };
     855                 :            : 
     856         [ +  - ]:          3 :     clearRange( pDoc, ScRange(0, 0, 0, 4, SAL_N_ELEMENTS(aData), 0));
     857                 :          3 :     ScAddress aPos(0,0,0);
     858         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData( pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
     859 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     860                 :            : 
     861         [ +  - ]:          3 :     pDoc->CalcAll();
     862                 :            : 
     863         [ +  + ]:         48 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aData); ++i)
     864                 :            :     {
     865         [ +  - ]:         45 :         rtl::OUString aVal = pDoc->GetString( 4, i, 0);
     866                 :            :         //std::cout << "row "<< i << ": " << rtl::OUStringToOString( aVal, RTL_TEXTENCODING_UTF8).getStr() << ", expected " << aData[i][3] << std::endl;
     867 [ +  - ][ +  - ]:         45 :         CPPUNIT_ASSERT_MESSAGE("Unexpected result for DATEDIF", aVal.equalsAscii( aData[i][3]));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     868                 :         45 :     }
     869                 :          3 : }
     870                 :            : 
     871                 :          3 : void testFuncINDIRECT(ScDocument* pDoc)
     872                 :            : {
     873         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 0, 10, 0)); // Clear A1:A11
     874                 :          3 :     rtl::OUString aTabName;
     875         [ +  - ]:          3 :     bool bGood = pDoc->GetName(0, aTabName);
     876 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to get sheet name.", bGood);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     877                 :            : 
     878                 :          3 :     rtl::OUString aTest = "Test", aRefErr = "#REF!";
     879         [ +  - ]:          3 :     pDoc->SetString(0, 10, 0, aTest);
     880 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", pDoc->GetString(0,10,0) == aTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     881                 :            : 
     882                 :          3 :     rtl::OUString aPrefix = "=INDIRECT(\"";
     883                 :            : 
     884                 :          3 :     rtl::OUString aFormula = aPrefix + aTabName + ".A11\")"; // Calc A1
     885         [ +  - ]:          3 :     pDoc->SetString(0, 0, 0, aFormula);
     886                 :          3 :     aFormula = aPrefix + aTabName + "!A11\")"; // Excel A1
     887         [ +  - ]:          3 :     pDoc->SetString(0, 1, 0, aFormula);
     888                 :          3 :     aFormula = aPrefix + aTabName + "!R11C1\")"; // Excel R1C1
     889         [ +  - ]:          3 :     pDoc->SetString(0, 2, 0, aFormula);
     890                 :          3 :     aFormula = aPrefix + aTabName + "!R11C1\";0)"; // Excel R1C1 (forced)
     891         [ +  - ]:          3 :     pDoc->SetString(0, 3, 0, aFormula);
     892                 :            : 
     893         [ +  - ]:          3 :     pDoc->CalcAll();
     894                 :            :     {
     895                 :            :         // Default is to use the current formula syntax, which is Calc A1.
     896                 :            :         const rtl::OUString* aChecks[] = {
     897                 :            :             &aTest, &aRefErr, &aRefErr, &aTest
     898                 :          3 :         };
     899                 :            : 
     900         [ +  + ]:         15 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     901                 :            :         {
     902         [ +  - ]:         12 :             rtl::OUString aVal = pDoc->GetString(0, i, 0);
     903 [ +  - ][ +  - ]:         12 :             CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     904                 :         12 :         }
     905                 :            :     }
     906                 :            : 
     907         [ +  - ]:          3 :     ScCalcConfig aConfig;
     908                 :          3 :     aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_OOO;
     909         [ +  - ]:          3 :     ScInterpreter::SetGlobalConfig(aConfig);
     910         [ +  - ]:          3 :     pDoc->CalcAll();
     911                 :            :     {
     912                 :            :         // Explicit Calc A1 syntax
     913                 :            :         const rtl::OUString* aChecks[] = {
     914                 :            :             &aTest, &aRefErr, &aRefErr, &aTest
     915                 :          3 :         };
     916                 :            : 
     917         [ +  + ]:         15 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     918                 :            :         {
     919         [ +  - ]:         12 :             rtl::OUString aVal = pDoc->GetString(0, i, 0);
     920 [ +  - ][ +  - ]:         12 :             CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     921                 :         12 :         }
     922                 :            :     }
     923                 :            : 
     924                 :          3 :     aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_XL_A1;
     925         [ +  - ]:          3 :     ScInterpreter::SetGlobalConfig(aConfig);
     926         [ +  - ]:          3 :     pDoc->CalcAll();
     927                 :            :     {
     928                 :            :         // Excel A1 syntax
     929                 :            :         const rtl::OUString* aChecks[] = {
     930                 :            :             &aRefErr, &aTest, &aRefErr, &aTest
     931                 :          3 :         };
     932                 :            : 
     933         [ +  + ]:         15 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     934                 :            :         {
     935         [ +  - ]:         12 :             rtl::OUString aVal = pDoc->GetString(0, i, 0);
     936 [ +  - ][ +  - ]:         12 :             CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     937                 :         12 :         }
     938                 :            :     }
     939                 :            : 
     940                 :          3 :     aConfig.meStringRefAddressSyntax = formula::FormulaGrammar::CONV_XL_R1C1;
     941         [ +  - ]:          3 :     ScInterpreter::SetGlobalConfig(aConfig);
     942         [ +  - ]:          3 :     pDoc->CalcAll();
     943                 :            :     {
     944                 :            :         // Excel R1C1 syntax
     945                 :            :         const rtl::OUString* aChecks[] = {
     946                 :            :             &aRefErr, &aRefErr, &aTest, &aTest
     947                 :          3 :         };
     948                 :            : 
     949         [ +  + ]:         15 :         for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
     950                 :            :         {
     951         [ +  - ]:         12 :             rtl::OUString aVal = pDoc->GetString(0, i, 0);
     952 [ +  - ][ +  - ]:         12 :             CPPUNIT_ASSERT_MESSAGE("Wrong value!", aVal == *aChecks[i]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     953                 :         12 :         }
     954                 :          3 :     }
     955                 :          3 : }
     956                 :            : 
     957                 :          3 : void Test::testCellFunctions()
     958                 :            : {
     959                 :          3 :     rtl::OUString aTabName("foo");
     960 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     961         [ +  - ]:          3 :                             m_pDoc->InsertTab (0, aTabName));
     962                 :            : 
     963         [ +  - ]:          3 :     testFuncSUM(m_pDoc);
     964         [ +  - ]:          3 :     testFuncPRODUCT(m_pDoc);
     965         [ +  - ]:          3 :     testFuncN(m_pDoc);
     966         [ +  - ]:          3 :     testFuncCOUNTIF(m_pDoc);
     967         [ +  - ]:          3 :     testFuncVLOOKUP(m_pDoc);
     968         [ +  - ]:          3 :     testFuncMATCH(m_pDoc);
     969         [ +  - ]:          3 :     testFuncCELL(m_pDoc);
     970         [ +  - ]:          3 :     testFuncDATEDIF(m_pDoc);
     971         [ +  - ]:          3 :     testFuncINDIRECT(m_pDoc);
     972                 :            : 
     973         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
     974                 :          3 : }
     975                 :            : 
     976                 :          3 : void Test::testSheetsFunc()
     977                 :            : {
     978                 :          3 :     rtl::OUString aTabName1("test1");
     979                 :          3 :     rtl::OUString aTabName2("test2");
     980 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     981         [ +  - ]:          3 :                             m_pDoc->InsertTab (SC_TAB_APPEND, aTabName1));
     982                 :            : 
     983         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, OUString("=SHEETS()"));
     984         [ +  - ]:          3 :     m_pDoc->CalcFormulaTree(false, true);
     985                 :            :     double original;
     986         [ +  - ]:          3 :     m_pDoc->GetValue(0, 0, 0, original);
     987                 :            : 
     988 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("result of SHEETS() should equal the number of sheets, but doesn't.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     989         [ +  - ]:          3 :                            static_cast<SCTAB>(original) == m_pDoc->GetTableCount());
     990                 :            : 
     991 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     992         [ +  - ]:          3 :                             m_pDoc->InsertTab (SC_TAB_APPEND, aTabName2));
     993                 :            : 
     994                 :            :     double modified;
     995         [ +  - ]:          3 :     m_pDoc->GetValue(0, 0, 0, modified);
     996 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("result of SHEETS() did not get updated after sheet insertion.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     997         [ +  - ]:          3 :                            modified - original == 1.0);
     998                 :            : 
     999         [ +  - ]:          3 :     SCTAB nTabCount = m_pDoc->GetTableCount();
    1000         [ +  - ]:          3 :     m_pDoc->DeleteTab(--nTabCount);
    1001                 :            : 
    1002         [ +  - ]:          3 :     m_pDoc->GetValue(0, 0, 0, modified);
    1003 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("result of SHEETS() did not get updated after sheet removal.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1004         [ +  - ]:          3 :                            modified - original == 0.0);
    1005                 :            : 
    1006         [ +  - ]:          3 :     m_pDoc->DeleteTab(--nTabCount);
    1007                 :          3 : }
    1008                 :            : 
    1009                 :          3 : void Test::testVolatileFunc()
    1010                 :            : {
    1011                 :          3 :     rtl::OUString aTabName("foo");
    1012 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1013         [ +  - ]:          3 :                             m_pDoc->InsertTab (0, aTabName));
    1014                 :            : 
    1015                 :          3 :     double val = 1;
    1016         [ +  - ]:          3 :     m_pDoc->SetValue(0, 0, 0, val);
    1017         [ +  - ]:          3 :     m_pDoc->SetString(0, 1, 0, OUString("=IF(A1>0;NOW();0"));
    1018                 :            :     double now1;
    1019         [ +  - ]:          3 :     m_pDoc->GetValue(0, 1, 0, now1);
    1020 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Value of NOW() should be positive.", now1 > 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1021                 :            : 
    1022                 :          3 :     val = 0;
    1023         [ +  - ]:          3 :     m_pDoc->SetValue(0, 0, 0, val);
    1024         [ +  - ]:          3 :     m_pDoc->CalcFormulaTree(false, true);
    1025                 :            :     double zero;
    1026         [ +  - ]:          3 :     m_pDoc->GetValue(0, 1, 0, zero);
    1027 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Result should equal the 3rd parameter of IF, which is zero.", zero == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1028                 :            : 
    1029                 :          3 :     val = 1;
    1030         [ +  - ]:          3 :     m_pDoc->SetValue(0, 0, 0, val);
    1031         [ +  - ]:          3 :     m_pDoc->CalcFormulaTree(false, true);
    1032                 :            :     double now2;
    1033         [ +  - ]:          3 :     m_pDoc->GetValue(0, 1, 0, now2);
    1034 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Result should be the value of NOW() again.", (now2 - now1) >= 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1035                 :            : 
    1036         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    1037                 :          3 : }
    1038                 :            : 
    1039                 :          3 : void Test::testFuncParam()
    1040                 :            : {
    1041                 :          3 :     rtl::OUString aTabName("foo");
    1042 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1043         [ +  - ]:          3 :                             m_pDoc->InsertTab (0, aTabName));
    1044                 :            : 
    1045                 :            :     // First, the normal case, with no missing parameters.
    1046         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, OUString("=AVERAGE(1;2;3)"));
    1047         [ +  - ]:          3 :     m_pDoc->CalcFormulaTree(false, true);
    1048                 :            :     double val;
    1049         [ +  - ]:          3 :     m_pDoc->GetValue(0, 0, 0, val);
    1050 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1051                 :            : 
    1052                 :            :     // Now function with missing parameters.  Missing values should be treated
    1053                 :            :     // as zeros.
    1054         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, OUString("=AVERAGE(1;;;)"));
    1055         [ +  - ]:          3 :     m_pDoc->CalcFormulaTree(false, true);
    1056         [ +  - ]:          3 :     m_pDoc->GetValue(0, 0, 0, val);
    1057 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 0.25);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1058                 :            : 
    1059                 :            :     // Conversion of string to numeric argument.
    1060         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, OUString("=\"\"+3"));    // empty string
    1061         [ +  - ]:          3 :     m_pDoc->SetString(0, 1, 0, OUString("=\" \"+3"));   // only blank
    1062         [ +  - ]:          3 :     m_pDoc->SetString(0, 2, 0, OUString("=\" 4 \"+3")); // number in blanks
    1063         [ +  - ]:          3 :     m_pDoc->SetString(0, 3, 0, OUString("=\" x \"+3")); // non-numeric => #VALUE! error
    1064                 :            : 
    1065                 :          3 :     rtl::OUString aVal;
    1066         [ +  - ]:          3 :     ScCalcConfig aConfig;
    1067                 :            : 
    1068                 :            :     // With "Empty string as zero" option.
    1069                 :          3 :     aConfig.mbEmptyStringAsZero = true;
    1070         [ +  - ]:          3 :     ScInterpreter::SetGlobalConfig(aConfig);
    1071         [ +  - ]:          3 :     m_pDoc->CalcAll();
    1072         [ +  - ]:          3 :     m_pDoc->GetValue(0, 0, 0, val);
    1073 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1074         [ +  - ]:          3 :     m_pDoc->GetValue(0, 1, 0, val);
    1075 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1076         [ +  - ]:          3 :     m_pDoc->GetValue(0, 2, 0, val);
    1077 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 7);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1078         [ +  - ]:          3 :     aVal = m_pDoc->GetString( 0, 3, 0);
    1079 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1080                 :            : 
    1081                 :            :     // Without "Empty string as zero" option.
    1082                 :          3 :     aConfig.mbEmptyStringAsZero = false;
    1083         [ +  - ]:          3 :     ScInterpreter::SetGlobalConfig(aConfig);
    1084         [ +  - ]:          3 :     m_pDoc->CalcAll();
    1085         [ +  - ]:          3 :     aVal = m_pDoc->GetString( 0, 0, 0);
    1086 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1087         [ +  - ]:          3 :     aVal = m_pDoc->GetString( 0, 1, 0);
    1088 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1089         [ +  - ]:          3 :     m_pDoc->GetValue(0, 2, 0, val);
    1090 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", val == 7);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1091         [ +  - ]:          3 :     aVal = m_pDoc->GetString( 0, 3, 0);
    1092 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect result", aVal == "#VALUE!");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1093                 :            : 
    1094         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    1095                 :          3 : }
    1096                 :            : 
    1097                 :          3 : void Test::testNamedRange()
    1098                 :            : {
    1099                 :            :     struct {
    1100                 :            :         const char* pName; const char* pExpr; sal_uInt16 nIndex;
    1101                 :            :     } aNames[] = {
    1102                 :            :         { "Divisor",  "$Sheet1.$A$1:$A$1048576", 1 },
    1103                 :            :         { "MyRange1", "$Sheet1.$A$1:$A$100",     2 },
    1104                 :            :         { "MyRange2", "$Sheet1.$B$1:$B$100",     3 },
    1105                 :            :         { "MyRange3", "$Sheet1.$C$1:$C$100",     4 }
    1106                 :          3 :     };
    1107                 :            : 
    1108                 :          3 :     rtl::OUString aTabName("Sheet1");
    1109 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE ("failed to insert sheet",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1110         [ +  - ]:          3 :                             m_pDoc->InsertTab (0, aTabName));
    1111                 :            : 
    1112         [ +  - ]:          3 :     m_pDoc->SetValue (0, 0, 0, 101);
    1113                 :            : 
    1114                 :          3 :     ScAddress aA1(0, 0, 0);
    1115 [ +  - ][ +  - ]:          3 :     ScRangeName* pNewRanges = new ScRangeName();
    1116         [ +  + ]:         15 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
    1117                 :            :     {
    1118                 :            :         ScRangeData* pNew = new ScRangeData(
    1119                 :            :             m_pDoc,
    1120                 :            :             rtl::OUString::createFromAscii(aNames[i].pName),
    1121                 :            :             rtl::OUString::createFromAscii(aNames[i].pExpr),
    1122 [ +  - ][ +  - ]:         12 :             aA1, 0, formula::FormulaGrammar::GRAM_ENGLISH);
         [ +  - ][ +  - ]
    1123                 :         12 :         pNew->SetIndex(aNames[i].nIndex);
    1124         [ +  - ]:         12 :         bool bSuccess = pNewRanges->insert(pNew);
    1125 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE ("insertion failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1126                 :            :     }
    1127                 :            : 
    1128                 :            :     // Make sure the index lookup does the right thing.
    1129         [ +  + ]:         15 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
    1130                 :            :     {
    1131         [ +  - ]:         12 :         const ScRangeData* p = pNewRanges->findByIndex(aNames[i].nIndex);
    1132 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed.", p);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1133                 :         12 :         rtl::OUString aName = p->GetName();
    1134 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved.", aName.equalsAscii(aNames[i].pName));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1135                 :         12 :     }
    1136                 :            : 
    1137                 :            :     // Test usage in formula expression.
    1138         [ +  - ]:          3 :     m_pDoc->SetRangeName(pNewRanges);
    1139         [ +  - ]:          3 :     m_pDoc->SetString (1, 0, 0, rtl::OUString("=A1/Divisor"));
    1140         [ +  - ]:          3 :     m_pDoc->CalcAll();
    1141                 :            : 
    1142                 :            :     double result;
    1143         [ +  - ]:          3 :     m_pDoc->GetValue (1, 0, 0, result);
    1144 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE ("calculation failed", result == 1.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1145                 :            : 
    1146                 :            :     // Test copy-ability of range names.
    1147 [ +  - ][ +  - ]:          3 :     ScRangeName* pCopiedRanges = new ScRangeName(*pNewRanges);
    1148         [ +  - ]:          3 :     m_pDoc->SetRangeName(pCopiedRanges);
    1149                 :            :     // Make sure the index lookup still works.
    1150         [ +  + ]:         15 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aNames); ++i)
    1151                 :            :     {
    1152         [ +  - ]:         12 :         const ScRangeData* p = pCopiedRanges->findByIndex(aNames[i].nIndex);
    1153 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE("lookup of range name by index failed with the copied instance.", p);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1154                 :         12 :         rtl::OUString aName = p->GetName();
    1155 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE("wrong range name is retrieved with the copied instance.", aName.equalsAscii(aNames[i].pName));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1156                 :         12 :     }
    1157                 :            : 
    1158         [ +  - ]:          3 :     m_pDoc->SetRangeName(NULL); // Delete the names.
    1159         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    1160                 :          3 : }
    1161                 :            : 
    1162                 :          3 : void Test::testCSV()
    1163                 :            : {
    1164                 :          3 :     const int English = 0, European = 1;
    1165                 :            :     struct {
    1166                 :            :         const char *pStr; int eSep; bool bResult; double nValue;
    1167                 :            :     } aTests[] = {
    1168                 :            :         { "foo",       English,  false, 0.0 },
    1169                 :            :         { "1.0",       English,  true,  1.0 },
    1170                 :            :         { "1,0",       English,  false, 0.0 },
    1171                 :            :         { "1.0",       European, false, 0.0 },
    1172                 :            :         { "1.000",     European, true,  1000.0 },
    1173                 :            :         { "1,000",     European, true,  1.0 },
    1174                 :            :         { "1.000",     English,  true,  1.0 },
    1175                 :            :         { "1,000",     English,  true,  1000.0 },
    1176                 :            :         { " 1.0",      English,  true,  1.0 },
    1177                 :            :         { " 1.0  ",    English,  true,  1.0 },
    1178                 :            :         { "1.0 ",      European, false, 0.0 },
    1179                 :            :         { "1.000",     European, true,  1000.0 },
    1180                 :            :         { "1137.999",  English,  true,  1137.999 },
    1181                 :            :         { "1.000.00",  European, false, 0.0 }
    1182                 :          3 :     };
    1183         [ +  + ]:         45 :     for (sal_uInt32 i = 0; i < SAL_N_ELEMENTS(aTests); i++) {
    1184         [ +  - ]:         42 :         rtl::OUString aStr(aTests[i].pStr, strlen (aTests[i].pStr), RTL_TEXTENCODING_UTF8);
    1185                 :         42 :         double nValue = 0.0;
    1186                 :            :         bool bResult = ScStringUtil::parseSimpleNumber
    1187                 :            :                 (aStr, aTests[i].eSep == English ? '.' : ',',
    1188                 :            :                  aTests[i].eSep == English ? ',' : '.',
    1189 [ +  + ][ +  + ]:         42 :                  nValue);
                 [ +  - ]
    1190 [ +  - ][ +  - ]:         42 :         CPPUNIT_ASSERT_MESSAGE ("CSV numeric detection failure", bResult == aTests[i].bResult);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1191 [ +  - ][ +  - ]:         42 :         CPPUNIT_ASSERT_MESSAGE ("CSV numeric value failure", nValue == aTests[i].nValue);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1192                 :         42 :     }
    1193                 :          3 : }
    1194                 :            : 
    1195                 :            : template<typename Evaluator>
    1196                 :         12 : void checkMatrixElements(const ScMatrix& rMat)
    1197                 :            : {
    1198                 :            :     SCSIZE nC, nR;
    1199 [ +  - ][ +  - ]:         12 :     rMat.GetDimensions(nC, nR);
         [ +  - ][ +  - ]
    1200                 :            :     Evaluator aEval;
    1201 [ +  + ][ +  + ]:         96 :     for (SCSIZE i = 0; i < nC; ++i)
         [ +  + ][ +  + ]
    1202                 :            :     {
    1203 [ +  + ][ +  + ]:       1524 :         for (SCSIZE j = 0; j < nR; ++j)
         [ +  + ][ +  + ]
    1204                 :            :         {
    1205 [ +  - ][ +  - ]:       1440 :             aEval(i, j, rMat.Get(i, j));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1206                 :            :         }
    1207                 :            :     }
    1208                 :         12 : }
    1209                 :            : 
    1210                 :            : struct AllZeroMatrix
    1211                 :            : {
    1212                 :        120 :     void operator() (SCSIZE /*nCol*/, SCSIZE /*nRow*/, const ScMatrixValue& rVal) const
    1213                 :            :     {
    1214 [ +  - ][ +  - ]:        120 :         CPPUNIT_ASSERT_MESSAGE("element is not of numeric type", rVal.nType == SC_MATVAL_VALUE);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1215 [ +  - ][ +  - ]:        120 :         CPPUNIT_ASSERT_MESSAGE("element value must be zero", rVal.fVal == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1216                 :        120 :     }
    1217                 :            : };
    1218                 :            : 
    1219                 :            : struct PartiallyFilledZeroMatrix
    1220                 :            : {
    1221                 :        120 :     void operator() (SCSIZE nCol, SCSIZE nRow, const ScMatrixValue& rVal) const
    1222                 :            :     {
    1223 [ +  - ][ +  - ]:        120 :         CPPUNIT_ASSERT_MESSAGE("element is not of numeric type", rVal.nType == SC_MATVAL_VALUE);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1224 [ +  + ][ +  + ]:        120 :         if (1 <= nCol && nCol <= 2 && 2 <= nRow && nRow <= 8)
         [ +  + ][ +  + ]
    1225                 :            :         {
    1226 [ +  - ][ +  - ]:         42 :             CPPUNIT_ASSERT_MESSAGE("element value must be 3.0", rVal.fVal == 3.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1227                 :            :         }
    1228                 :            :         else
    1229                 :            :         {
    1230 [ +  - ][ +  - ]:         78 :             CPPUNIT_ASSERT_MESSAGE("element value must be zero", rVal.fVal == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1231                 :            :         }
    1232                 :        120 :     }
    1233                 :            : };
    1234                 :            : 
    1235                 :            : struct AllEmptyMatrix
    1236                 :            : {
    1237                 :        600 :     void operator() (SCSIZE /*nCol*/, SCSIZE /*nRow*/, const ScMatrixValue& rVal) const
    1238                 :            :     {
    1239 [ +  - ][ +  - ]:        600 :         CPPUNIT_ASSERT_MESSAGE("element is not of empty type", rVal.nType == SC_MATVAL_EMPTY);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1240 [ +  - ][ +  - ]:        600 :         CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal.fVal == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1241                 :        600 :     }
    1242                 :            : };
    1243                 :            : 
    1244                 :            : struct PartiallyFilledEmptyMatrix
    1245                 :            : {
    1246                 :        600 :     void operator() (SCSIZE nCol, SCSIZE nRow, const ScMatrixValue& rVal) const
    1247                 :            :     {
    1248 [ +  + ][ +  + ]:        600 :         if (nCol == 1 && nRow == 1)
    1249                 :            :         {
    1250 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element is not of boolean type", rVal.nType == SC_MATVAL_BOOLEAN);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1251 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.fVal == 1.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1252                 :            :         }
    1253 [ +  + ][ +  + ]:        597 :         else if (nCol == 4 && nRow == 5)
    1254                 :            :         {
    1255 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal.nType == SC_MATVAL_VALUE);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1256 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.fVal == -12.5);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1257                 :            :         }
    1258 [ +  + ][ +  + ]:        594 :         else if (nCol == 8 && nRow == 2)
    1259                 :            :         {
    1260 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element is not of value type", rVal.nType == SC_MATVAL_STRING);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1261 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element value is not what is expected", rVal.aStr == "Test");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1262                 :            :         }
    1263 [ +  + ][ +  + ]:        591 :         else if (nCol == 8 && nRow == 11)
    1264                 :            :         {
    1265 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("element is not of empty path type", rVal.nType == SC_MATVAL_EMPTYPATH);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1266 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal.fVal == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1267                 :            :         }
    1268                 :            :         else
    1269                 :            :         {
    1270 [ +  - ][ +  - ]:        588 :             CPPUNIT_ASSERT_MESSAGE("element is not of empty type", rVal.nType == SC_MATVAL_EMPTY);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1271 [ +  - ][ +  - ]:        588 :             CPPUNIT_ASSERT_MESSAGE("value of \"empty\" element is expected to be zero", rVal.fVal == 0.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1272                 :            :         }
    1273                 :        600 :     }
    1274                 :            : };
    1275                 :            : 
    1276                 :          3 : void Test::testMatrix()
    1277                 :            : {
    1278                 :          3 :     ScMatrixRef pMat;
    1279                 :            : 
    1280                 :            :     // First, test the zero matrix type.
    1281 [ +  - ][ +  - ]:          3 :     pMat = new ScMatrix(0, 0, 0.0);
                 [ +  - ]
    1282                 :            :     SCSIZE nC, nR;
    1283         [ +  - ]:          3 :     pMat->GetDimensions(nC, nR);
    1284 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("matrix is not empty", nC == 0 && nR == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1285         [ +  - ]:          3 :     pMat->Resize(4, 10, 0.0);
    1286         [ +  - ]:          3 :     pMat->GetDimensions(nC, nR);
    1287 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 4 && nR == 10);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1288 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("both 'and' and 'or' should evaluate to false",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    1289         [ +  - ]:          3 :                            !pMat->And() && !pMat->Or());
    1290                 :            : 
    1291                 :            :     // Resizing into a larger matrix should fill the void space with zeros.
    1292         [ +  - ]:          3 :     checkMatrixElements<AllZeroMatrix>(*pMat);
    1293                 :            : 
    1294         [ +  - ]:          3 :     pMat->FillDouble(3.0, 1, 2, 2, 8);
    1295         [ +  - ]:          3 :     checkMatrixElements<PartiallyFilledZeroMatrix>(*pMat);
    1296 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("matrix is expected to be numeric", pMat->IsNumeric());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1297 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("partially non-zero matrix should evaluate false on 'and' and true on 'or",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    1298         [ +  - ]:          3 :                            !pMat->And() && pMat->Or());
    1299         [ +  - ]:          3 :     pMat->FillDouble(5.0, 0, 0, nC-1, nR-1);
    1300 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("fully non-zero matrix should evaluate true both on 'and' and 'or",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
    1301         [ +  - ]:          3 :                            pMat->And() && pMat->Or());
    1302                 :            : 
    1303                 :            :     // Test the AND and OR evaluations.
    1304 [ +  - ][ +  - ]:          3 :     pMat = new ScMatrix(2, 2, 0.0);
                 [ +  - ]
    1305                 :            : 
    1306                 :            :     // Only some of the elements are non-zero.
    1307         [ +  - ]:          3 :     pMat->PutBoolean(true, 0, 0);
    1308         [ +  - ]:          3 :     pMat->PutDouble(1.0, 1, 1);
    1309 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1310 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect AND result", !pMat->And());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1311                 :            : 
    1312                 :            :     // All of the elements are non-zero.
    1313         [ +  - ]:          3 :     pMat->PutBoolean(true, 0, 1);
    1314         [ +  - ]:          3 :     pMat->PutDouble(2.3, 1, 0);
    1315 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect OR result", pMat->Or());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1316 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("incorrect AND result", pMat->And());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1317                 :            : 
    1318                 :            :     // Now test the emtpy matrix type.
    1319 [ +  - ][ +  - ]:          3 :     pMat = new ScMatrix(10, 20);
                 [ +  - ]
    1320         [ +  - ]:          3 :     pMat->GetDimensions(nC, nR);
    1321 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("matrix size is not as expected", nC == 10 && nR == 20);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1322         [ +  - ]:          3 :     checkMatrixElements<AllEmptyMatrix>(*pMat);
    1323                 :            : 
    1324         [ +  - ]:          3 :     pMat->PutBoolean(true, 1, 1);
    1325         [ +  - ]:          3 :     pMat->PutDouble(-12.5, 4, 5);
    1326                 :          3 :     rtl::OUString aStr("Test");
    1327         [ +  - ]:          3 :     pMat->PutString(aStr, 8, 2);
    1328         [ +  - ]:          3 :     pMat->PutEmptyPath(8, 11);
    1329 [ +  - ][ +  - ]:          3 :     checkMatrixElements<PartiallyFilledEmptyMatrix>(*pMat);
    1330                 :          3 : }
    1331                 :            : 
    1332                 :            : namespace {
    1333                 :            : 
    1334                 :            : struct DPFieldDef
    1335                 :            : {
    1336                 :            :     const char* pName;
    1337                 :            :     sheet::DataPilotFieldOrientation eOrient;
    1338                 :            : 
    1339                 :            :     /**
    1340                 :            :      * Function for data field.  It's used only for data field.  When 0, the
    1341                 :            :      * default function (SUM) is used.
    1342                 :            :      */
    1343                 :            :     int eFunc;
    1344                 :            : };
    1345                 :            : 
    1346                 :            : template<size_t _Size>
    1347                 :         15 : ScRange insertDPSourceData(ScDocument* pDoc, DPFieldDef aFields[], size_t nFieldCount, const char* aData[][_Size], size_t nDataCount)
    1348                 :            : {
    1349                 :            :     // Insert field names in row 0.
    1350 [ +  + ][ +  + ]:         66 :     for (size_t i = 0; i < nFieldCount; ++i)
    1351 [ +  - ][ +  - ]:         51 :         pDoc->SetString(static_cast<SCCOL>(i), 0, 0, OUString(aFields[i].pName, strlen(aFields[i].pName), RTL_TEXTENCODING_UTF8));
         [ +  - ][ +  - ]
    1352                 :            : 
    1353                 :            :     // Insert data into row 1 and downward.
    1354 [ +  + ][ +  + ]:         93 :     for (size_t i = 0; i < nDataCount; ++i)
    1355                 :            :     {
    1356                 :         78 :         SCROW nRow = static_cast<SCROW>(i) + 1;
    1357 [ +  + ][ +  + ]:        360 :         for (size_t j = 0; j < nFieldCount; ++j)
    1358                 :            :         {
    1359                 :        282 :             SCCOL nCol = static_cast<SCCOL>(j);
    1360 [ +  - ][ +  - ]:        282 :             pDoc->SetString(
         [ +  - ][ +  - ]
    1361                 :            :                 nCol, nRow, 0, OUString(aData[i][j], strlen(aData[i][j]), RTL_TEXTENCODING_UTF8));
    1362                 :            :         }
    1363                 :            :     }
    1364                 :            : 
    1365                 :         15 :     SCROW nRow1 = 0, nRow2 = 0;
    1366                 :         15 :     SCCOL nCol1 = 0, nCol2 = 0;
    1367 [ +  - ][ +  - ]:         15 :     pDoc->GetDataArea(0, nCol1, nRow1, nCol2, nRow2, true, false);
    1368 [ +  - ][ +  - ]:         15 :     CPPUNIT_ASSERT_MESSAGE("Data is expected to start from (col=0,row=0).", nCol1 == 0 && nRow1 == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    1369 [ +  - ][ +  - ]:         15 :     CPPUNIT_ASSERT_MESSAGE("Unexpected data range.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1370                 :            :                            nCol2 == static_cast<SCCOL>(nFieldCount - 1) && nRow2 == static_cast<SCROW>(nDataCount));
    1371                 :            : 
    1372                 :         15 :     ScRange aSrcRange(nCol1, nRow1, 0, nCol2, nRow2, 0);
    1373 [ +  - ][ +  - ]:         15 :     printRange(pDoc, aSrcRange, "Data sheet content");
    1374                 :         15 :     return aSrcRange;
    1375                 :            : }
    1376                 :            : 
    1377                 :            : template<size_t _Size>
    1378                 :         66 : bool checkDPTableOutput(ScDocument* pDoc, const ScRange& aOutRange, const char* aOutputCheck[][_Size], const char* pCaption)
    1379                 :            : {
    1380                 :         66 :     bool bResult = true;
    1381                 :         66 :     const ScAddress& s = aOutRange.aStart;
    1382                 :         66 :     const ScAddress& e = aOutRange.aEnd;
    1383 [ +  - ][ +  - ]:         66 :     SheetPrinter printer(e.Row() - s.Row() + 1, e.Col() - s.Col() + 1);
         [ +  - ][ +  - ]
    1384                 :         66 :     SCROW nOutRowSize = e.Row() - s.Row() + 1;
    1385                 :         66 :     SCCOL nOutColSize = e.Col() - s.Col() + 1;
    1386 [ +  + ][ +  + ]:        519 :     for (SCROW nRow = 0; nRow < nOutRowSize; ++nRow)
         [ +  + ][ +  + ]
    1387                 :            :     {
    1388 [ +  + ][ +  + ]:       1947 :         for (SCCOL nCol = 0; nCol < nOutColSize; ++nCol)
         [ +  + ][ +  + ]
    1389                 :            :         {
    1390                 :       1494 :             OUString aVal;
    1391   [ +  -  +  -  :       1494 :             pDoc->GetString(nCol + s.Col(), nRow + s.Row(), s.Tab(), aVal);
             +  -  +  - ]
    1392 [ +  - ][ +  - ]:       1494 :             printer.set(nRow, nCol, aVal);
         [ +  - ][ +  - ]
    1393                 :       1494 :             const char* p = aOutputCheck[nRow][nCol];
    1394 [ +  + ][ +  + ]:       1494 :             if (p)
         [ +  + ][ +  + ]
    1395                 :            :             {
    1396                 :       1116 :                 OUString aCheckVal = OUString::createFromAscii(p);
    1397                 :       1116 :                 bool bEqual = aCheckVal.equals(aVal);
    1398   [ -  +  -  +  :       1116 :                 if (!bEqual)
             -  +  -  + ]
    1399                 :            :                 {
    1400 [ #  # ][ #  # ]:          0 :                     cout << "Expected: " << aCheckVal << "  Actual: " << aVal << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1401                 :       1116 :                     bResult = false;
    1402                 :            :                 }
    1403                 :            :             }
    1404 [ -  + ][ -  + ]:        378 :             else if (!aVal.isEmpty())
         [ -  + ][ -  + ]
    1405                 :            :             {
    1406 [ #  # ][ #  # ]:          0 :                 cout << "Empty cell expected" << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1407                 :       1494 :                 bResult = false;
    1408                 :            :             }
    1409                 :            :         }
    1410                 :            :     }
    1411                 :         66 :     printer.print(pCaption);
    1412 [ +  - ][ +  - ]:         66 :     return bResult;
         [ +  - ][ +  - ]
    1413                 :            : }
    1414                 :            : 
    1415                 :         39 : ScDPObject* createDPFromSourceDesc(
    1416                 :            :     ScDocument* pDoc, const ScSheetSourceDesc& rDesc, DPFieldDef aFields[], size_t nFieldCount,
    1417                 :            :     bool bFilterButton)
    1418                 :            : {
    1419 [ +  - ][ +  - ]:         39 :     ScDPObject* pDPObj = new ScDPObject(pDoc);
    1420         [ +  - ]:         39 :     pDPObj->SetSheetDesc(rDesc);
    1421         [ +  - ]:         39 :     pDPObj->SetOutRange(ScAddress(0, 0, 1));
    1422                 :            : 
    1423         [ +  - ]:         39 :     ScDPSaveData aSaveData;
    1424                 :            :     // Set data pilot table output options.
    1425         [ +  - ]:         39 :     aSaveData.SetIgnoreEmptyRows(false);
    1426         [ +  - ]:         39 :     aSaveData.SetRepeatIfEmpty(false);
    1427         [ +  - ]:         39 :     aSaveData.SetColumnGrand(true);
    1428         [ +  - ]:         39 :     aSaveData.SetRowGrand(true);
    1429         [ +  - ]:         39 :     aSaveData.SetFilterButton(bFilterButton);
    1430         [ +  - ]:         39 :     aSaveData.SetDrillDown(true);
    1431                 :            : 
    1432                 :            :     // Check the sanity of the source range.
    1433         [ +  - ]:         39 :     const ScRange& rSrcRange = rDesc.GetSourceRange();
    1434                 :         39 :     SCROW nRow1 = rSrcRange.aStart.Row();
    1435                 :         39 :     SCROW nRow2 = rSrcRange.aEnd.Row();
    1436 [ +  - ][ +  - ]:         39 :     CPPUNIT_ASSERT_MESSAGE("source range contains no data!", nRow2 - nRow1 > 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1437                 :            : 
    1438                 :            :     // Set the dimension information.
    1439         [ +  + ]:        144 :     for (size_t i = 0; i < nFieldCount; ++i)
    1440                 :            :     {
    1441                 :        105 :         OUString aDimName = rtl::OUString::createFromAscii(aFields[i].pName);
    1442         [ +  - ]:        105 :         ScDPSaveDimension* pDim = aSaveData.GetNewDimensionByName(aDimName);
    1443         [ +  - ]:        105 :         pDim->SetOrientation(static_cast<sal_uInt16>(aFields[i].eOrient));
    1444         [ +  - ]:        105 :         pDim->SetUsedHierarchy(0);
    1445                 :            : 
    1446         [ +  + ]:        105 :         if (aFields[i].eOrient == sheet::DataPilotFieldOrientation_DATA)
    1447                 :            :         {
    1448                 :         45 :             sheet::GeneralFunction eFunc = sheet::GeneralFunction_SUM;
    1449         [ +  + ]:         45 :             if (aFields[i].eFunc)
    1450                 :         24 :                 eFunc = static_cast<sheet::GeneralFunction>(aFields[i].eFunc);
    1451                 :            : 
    1452         [ +  - ]:         45 :             pDim->SetFunction(eFunc);
    1453         [ +  - ]:         45 :             pDim->SetReferenceValue(NULL);
    1454                 :            :         }
    1455                 :            :         else
    1456                 :            :         {
    1457                 :         60 :             sheet::DataPilotFieldSortInfo aSortInfo;
    1458                 :         60 :             aSortInfo.IsAscending = true;
    1459                 :         60 :             aSortInfo.Mode = 2;
    1460         [ +  - ]:         60 :             pDim->SetSortInfo(&aSortInfo);
    1461                 :            : 
    1462                 :         60 :             sheet::DataPilotFieldLayoutInfo aLayInfo;
    1463                 :         60 :             aLayInfo.LayoutMode = 0;
    1464                 :         60 :             aLayInfo.AddEmptyLines = false;
    1465         [ +  - ]:         60 :             pDim->SetLayoutInfo(&aLayInfo);
    1466                 :         60 :             sheet::DataPilotFieldAutoShowInfo aShowInfo;
    1467                 :         60 :             aShowInfo.IsEnabled = false;
    1468                 :         60 :             aShowInfo.ShowItemsMode = 0;
    1469                 :         60 :             aShowInfo.ItemCount = 0;
    1470         [ +  - ]:         60 :             pDim->SetAutoShowInfo(&aShowInfo);
    1471                 :            :         }
    1472                 :        105 :     }
    1473                 :            : 
    1474                 :            :     // Don't forget the data layout dimension.
    1475         [ +  - ]:         39 :     ScDPSaveDimension* pDim = aSaveData.GetDataLayoutDimension();
    1476         [ +  - ]:         39 :     pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
    1477         [ +  - ]:         39 :     pDim->SetShowEmpty(true);
    1478                 :            : 
    1479         [ +  - ]:         39 :     pDPObj->SetSaveData(aSaveData);
    1480         [ +  - ]:         39 :     pDPObj->SetAlive(true);
    1481         [ +  - ]:         39 :     pDPObj->InvalidateData();
    1482                 :            : 
    1483         [ +  - ]:         39 :     return pDPObj;
    1484                 :            : }
    1485                 :            : 
    1486                 :         36 : ScDPObject* createDPFromRange(
    1487                 :            :     ScDocument* pDoc, const ScRange& rRange, DPFieldDef aFields[], size_t nFieldCount,
    1488                 :            :     bool bFilterButton)
    1489                 :            : {
    1490         [ +  - ]:         36 :     ScSheetSourceDesc aSheetDesc(pDoc);
    1491         [ +  - ]:         36 :     aSheetDesc.SetSourceRange(rRange);
    1492 [ +  - ][ +  - ]:         36 :     return createDPFromSourceDesc(pDoc, aSheetDesc, aFields, nFieldCount, bFilterButton);
    1493                 :            : }
    1494                 :            : 
    1495                 :         57 : ScRange refresh(ScDPObject* pDPObj)
    1496                 :            : {
    1497                 :         57 :     bool bOverFlow = false;
    1498         [ +  - ]:         57 :     ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow);
    1499 [ +  - ][ +  - ]:         57 :     CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1500                 :            : 
    1501         [ +  - ]:         57 :     pDPObj->Output(aOutRange.aStart);
    1502                 :         57 :     aOutRange = pDPObj->GetOutRange();
    1503                 :         57 :     return aOutRange;
    1504                 :            : }
    1505                 :            : 
    1506                 :         12 : ScRange refreshGroups(ScDPCollection* pDPs, ScDPObject* pDPObj)
    1507                 :            : {
    1508                 :            :     // We need to first create group data in the cache, then the group data in
    1509                 :            :     // the object.
    1510         [ +  - ]:         12 :     std::set<ScDPObject*> aRefs;
    1511         [ +  - ]:         12 :     bool bSuccess = pDPs->ReloadGroupsInCache(pDPObj, aRefs);
    1512 [ +  - ][ +  - ]:         12 :     CPPUNIT_ASSERT_MESSAGE("Failed to reload group data in cache.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1513 [ +  - ][ +  - ]:         12 :     CPPUNIT_ASSERT_MESSAGE("There should be only one table linked to this cache.", aRefs.size() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1514         [ +  - ]:         12 :     pDPObj->ReloadGroupTableData();
    1515                 :            : 
    1516         [ +  - ]:         12 :     return refresh(pDPObj);
    1517                 :            : }
    1518                 :            : 
    1519                 :            : class AutoCalcSwitch
    1520                 :            : {
    1521                 :            :     ScDocument* mpDoc;
    1522                 :            :     bool mbOldValue;
    1523                 :            : public:
    1524                 :          3 :     AutoCalcSwitch(ScDocument* pDoc, bool bAutoCalc) : mpDoc(pDoc), mbOldValue(pDoc->GetAutoCalc())
    1525                 :            :     {
    1526                 :          3 :         mpDoc->SetAutoCalc(bAutoCalc);
    1527                 :          3 :     }
    1528                 :            : 
    1529                 :          3 :     ~AutoCalcSwitch()
    1530                 :            :     {
    1531                 :          3 :         mpDoc->SetAutoCalc(mbOldValue);
    1532                 :          3 :     }
    1533                 :            : };
    1534                 :            : 
    1535                 :            : }
    1536                 :            : 
    1537                 :          3 : void Test::testPivotTable()
    1538                 :            : {
    1539         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    1540         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    1541                 :            : 
    1542                 :            :     // Dimension definition
    1543                 :            :     DPFieldDef aFields[] = {
    1544                 :            :         { "Name",  sheet::DataPilotFieldOrientation_ROW, 0 },
    1545                 :            :         { "Group", sheet::DataPilotFieldOrientation_COLUMN, 0 },
    1546                 :            :         { "Score", sheet::DataPilotFieldOrientation_DATA, 0 }
    1547                 :          3 :     };
    1548                 :            : 
    1549                 :            :     // Raw data
    1550                 :            :     const char* aData[][3] = {
    1551                 :            :         { "Andy",    "A", "30" },
    1552                 :            :         { "Bruce",   "A", "20" },
    1553                 :            :         { "Charlie", "B", "45" },
    1554                 :            :         { "David",   "B", "12" },
    1555                 :            :         { "Edward",  "C",  "8" },
    1556                 :            :         { "Frank",   "C", "15" },
    1557                 :          3 :     };
    1558                 :            : 
    1559                 :          3 :     size_t nFieldCount = SAL_N_ELEMENTS(aFields);
    1560                 :          3 :     size_t nDataCount = SAL_N_ELEMENTS(aData);
    1561                 :            : 
    1562         [ +  - ]:          3 :     ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
    1563                 :          3 :     SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
    1564                 :          3 :     SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
    1565                 :            : 
    1566                 :            :     ScDPObject* pDPObj = createDPFromRange(
    1567         [ +  - ]:          3 :         m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
    1568                 :            : 
    1569         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    1570         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    1571 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1572 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1573         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    1574 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    1575                 :            : 
    1576                 :          3 :     bool bOverFlow = false;
    1577         [ +  - ]:          3 :     ScRange aOutRange = pDPObj->GetNewOutputRange(bOverFlow);
    1578 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Table overflow!?", !bOverFlow);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1579                 :            : 
    1580         [ +  - ]:          3 :     pDPObj->Output(aOutRange.aStart);
    1581                 :          3 :     aOutRange = pDPObj->GetOutRange();
    1582                 :            :     {
    1583                 :            :         // Expected output table content.  0 = empty cell
    1584                 :            :         const char* aOutputCheck[][5] = {
    1585                 :            :             { "Sum - Score", "Group", 0, 0, 0 },
    1586                 :            :             { "Name", "A", "B", "C", "Total Result" },
    1587                 :            :             { "Andy", "30", 0, 0, "30" },
    1588                 :            :             { "Bruce", "20", 0, 0, "20" },
    1589                 :            :             { "Charlie", 0, "45", 0, "45" },
    1590                 :            :             { "David", 0, "12", 0, "12" },
    1591                 :            :             { "Edward", 0, 0, "8", "8" },
    1592                 :            :             { "Frank", 0, 0, "15", "15" },
    1593                 :            :             { "Total Result", "50", "57", "23", "130" }
    1594                 :          3 :         };
    1595                 :            : 
    1596         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
    1597 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1598                 :            :     }
    1599 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1600                 :            : 
    1601                 :            :     // Update the cell values.
    1602                 :          3 :     double aData2[] = { 100, 200, 300, 400, 500, 600 };
    1603         [ +  + ]:         21 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aData2); ++i)
    1604                 :            :     {
    1605                 :         18 :         SCROW nRow = i + 1;
    1606         [ +  - ]:         18 :         m_pDoc->SetValue(2, nRow, 0, aData2[i]);
    1607                 :            :     }
    1608                 :            : 
    1609         [ +  - ]:          3 :     printRange(m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), "Data sheet content (modified)");
    1610                 :            : 
    1611                 :            :     // Now, create a copy of the datapilot object for the updated table, but
    1612                 :            :     // don't reload the cache which should force the copy to use the old data
    1613                 :            :     // from the cache.
    1614 [ +  - ][ +  - ]:          3 :     ScDPObject* pDPObj2 = new ScDPObject(*pDPObj);
    1615         [ +  - ]:          3 :     pDPs->InsertNewTable(pDPObj2);
    1616                 :            : 
    1617                 :          3 :     aOutRange = pDPObj2->GetOutRange();
    1618         [ +  - ]:          3 :     pDPObj2->ClearTableData();
    1619         [ +  - ]:          3 :     pDPObj2->Output(aOutRange.aStart);
    1620                 :            :     {
    1621                 :            :         // Expected output table content.  0 = empty cell
    1622                 :            :         const char* aOutputCheck[][5] = {
    1623                 :            :             { "Sum - Score", "Group", 0, 0, 0 },
    1624                 :            :             { "Name", "A", "B", "C", "Total Result" },
    1625                 :            :             { "Andy", "30", 0, 0, "30" },
    1626                 :            :             { "Bruce", "20", 0, 0, "20" },
    1627                 :            :             { "Charlie", 0, "45", 0, "45" },
    1628                 :            :             { "David", 0, "12", 0, "12" },
    1629                 :            :             { "Edward", 0, 0, "8", "8" },
    1630                 :            :             { "Frank", 0, 0, "15", "15" },
    1631                 :            :             { "Total Result", "50", "57", "23", "130" }
    1632                 :          3 :         };
    1633                 :            : 
    1634         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (from old cache)");
    1635 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1636                 :            :     }
    1637                 :            : 
    1638 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1639                 :            : 
    1640                 :            :     // Free the first datapilot object after the 2nd one gets reloaded, to
    1641                 :            :     // prevent the data cache from being deleted before the reload.
    1642         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    1643                 :            : 
    1644 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be only one data cache.", pDPs->GetSheetCaches().size() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1645                 :            : 
    1646                 :            :     // This time clear the cache to refresh the data from the source range.
    1647 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("This datapilot should be based on sheet data.", pDPObj2->IsSheetData());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1648         [ +  - ]:          3 :     std::set<ScDPObject*> aRefs;
    1649         [ +  - ]:          3 :     sal_uLong nErrId = pDPs->ReloadCache(pDPObj2, aRefs);
    1650 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache reload failed.", nErrId == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1651 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Reloading a cache shouldn't remove any cache.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1652         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size() == 1);
    1653                 :            : 
    1654         [ +  - ]:          3 :     pDPObj2->ClearTableData();
    1655         [ +  - ]:          3 :     pDPObj2->Output(aOutRange.aStart);
    1656                 :            : 
    1657                 :            :     {
    1658                 :            :         // Expected output table content.  0 = empty cell
    1659                 :            :         const char* aOutputCheck[][5] = {
    1660                 :            :             { "Sum - Score", "Group", 0, 0, 0 },
    1661                 :            :             { "Name", "A", "B", "C", "Total Result" },
    1662                 :            :             { "Andy", "100", 0, 0, "100" },
    1663                 :            :             { "Bruce", "200", 0, 0, "200" },
    1664                 :            :             { "Charlie", 0, "300", 0, "300" },
    1665                 :            :             { "David", 0, "400", 0, "400" },
    1666                 :            :             { "Edward", 0, 0, "500", "500" },
    1667                 :            :             { "Frank", 0, 0, "600", "600" },
    1668                 :            :             { "Total Result", "300", "700", "1100", "2100" }
    1669                 :          3 :         };
    1670                 :            : 
    1671         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (refreshed)");
    1672 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1673                 :            :     }
    1674                 :            : 
    1675 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache should be here.", pDPs->GetSheetCaches().hasCache(aSrcRange));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1676                 :            : 
    1677                 :            :     // Swap the two sheets.
    1678         [ +  - ]:          3 :     m_pDoc->MoveTab(1, 0);
    1679 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Swapping the sheets shouldn't remove the cache.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1680         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size() == 1);
    1681 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache should have moved.", !pDPs->GetSheetCaches().hasCache(aSrcRange));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1682                 :          3 :     aSrcRange.aStart.SetTab(1);
    1683                 :          3 :     aSrcRange.aEnd.SetTab(1);
    1684 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache should be here.", pDPs->GetSheetCaches().hasCache(aSrcRange));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1685                 :            : 
    1686         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj2);
    1687 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1688         [ +  - ]:          3 :                            pDPs->GetCount() == 0);
    1689                 :            : 
    1690 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("There shouldn't be any more data cache.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1691         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size() == 0);
    1692                 :            : 
    1693                 :            :     // Insert a brand new pivot table object once again, but this time, don't
    1694                 :            :     // create the output to avoid creating a data cache.
    1695         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    1696         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    1697                 :            : 
    1698                 :            :     pDPObj = createDPFromRange(
    1699         [ +  - ]:          3 :         m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
    1700         [ +  - ]:          3 :     bSuccess = pDPs->InsertNewTable(pDPObj);
    1701 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1702 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1703         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    1704 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    1705 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Data cache shouldn't exist yet before creating the table output.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1706         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size() == 0);
    1707                 :            : 
    1708                 :            :     // Now, "refresh" the table.  This should still return a reference to self
    1709                 :            :     // even with the absence of data cache.
    1710                 :          3 :     aRefs.clear();
    1711         [ +  - ]:          3 :     pDPs->ReloadCache(pDPObj, aRefs);
    1712 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("It should return the same object as a reference.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    1713         [ +  - ]:          3 :                            aRefs.size() == 1 && *aRefs.begin() == pDPObj);
    1714                 :            : 
    1715         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    1716                 :            : 
    1717         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    1718         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    1719                 :          3 : }
    1720                 :            : 
    1721                 :          3 : void Test::testPivotTableLabels()
    1722                 :            : {
    1723         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    1724         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    1725                 :            : 
    1726                 :            :     // Dimension definition
    1727                 :            :     DPFieldDef aFields[] = {
    1728                 :            :         { "Software", sheet::DataPilotFieldOrientation_ROW, 0 },
    1729                 :            :         { "Version",  sheet::DataPilotFieldOrientation_COLUMN, 0 },
    1730                 :            :         { "1.2.3",    sheet::DataPilotFieldOrientation_DATA, 0 }
    1731                 :          3 :     };
    1732                 :            : 
    1733                 :            :     // Raw data
    1734                 :            :     const char* aData[][3] = {
    1735                 :            :         { "LibreOffice", "3.3.0", "30" },
    1736                 :            :         { "LibreOffice", "3.3.1", "20" },
    1737                 :            :         { "LibreOffice", "3.4.0", "45" },
    1738                 :          3 :     };
    1739                 :            : 
    1740                 :          3 :     size_t nFieldCount = SAL_N_ELEMENTS(aFields);
    1741                 :          3 :     size_t nDataCount = SAL_N_ELEMENTS(aData);
    1742                 :            : 
    1743         [ +  - ]:          3 :     ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
    1744                 :          3 :     SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
    1745                 :          3 :     SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
    1746                 :            : 
    1747                 :            :     ScDPObject* pDPObj = createDPFromRange(
    1748         [ +  - ]:          3 :         m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
    1749                 :            : 
    1750         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    1751         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    1752 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1753 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1754         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    1755 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    1756                 :            : 
    1757         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    1758                 :            :     {
    1759                 :            :         // Expected output table content.  0 = empty cell
    1760                 :            :         const char* aOutputCheck[][5] = {
    1761                 :            :             { "Sum - 1.2.3", "Version", 0, 0, 0 },
    1762                 :            :             { "Software", "3.3.0", "3.3.1", "3.4.0", "Total Result" },
    1763                 :            :             { "LibreOffice", "30", "20", "45", "95" },
    1764                 :            :             { "Total Result", "30", "20", "45", "95" }
    1765                 :          3 :         };
    1766                 :            : 
    1767         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
    1768 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1769                 :            :     }
    1770                 :            : 
    1771         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    1772                 :            : 
    1773         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    1774         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    1775                 :          3 : }
    1776                 :            : 
    1777                 :          3 : void Test::testPivotTableDateLabels()
    1778                 :            : {
    1779         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    1780         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    1781                 :            : 
    1782                 :            :     // Dimension definition
    1783                 :            :     DPFieldDef aFields[] = {
    1784                 :            :         { "Name",  sheet::DataPilotFieldOrientation_ROW, 0 },
    1785                 :            :         { "Date",  sheet::DataPilotFieldOrientation_COLUMN, 0 },
    1786                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, 0 }
    1787                 :          3 :     };
    1788                 :            : 
    1789                 :            :     // Raw data
    1790                 :            :     const char* aData[][3] = {
    1791                 :            :         { "Zena",   "2011-1-1", "30" },
    1792                 :            :         { "Yodel",  "2011-1-2", "20" },
    1793                 :            :         { "Xavior", "2011-1-3", "45" }
    1794                 :          3 :     };
    1795                 :            : 
    1796                 :          3 :     size_t nFieldCount = SAL_N_ELEMENTS(aFields);
    1797                 :          3 :     size_t nDataCount = SAL_N_ELEMENTS(aData);
    1798                 :            : 
    1799         [ +  - ]:          3 :     ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
    1800                 :          3 :     SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
    1801                 :          3 :     SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
    1802                 :            : 
    1803                 :            :     ScDPObject* pDPObj = createDPFromRange(
    1804         [ +  - ]:          3 :         m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, false);
    1805                 :            : 
    1806         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    1807         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    1808 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1809 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1810         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    1811 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    1812                 :            : 
    1813         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    1814                 :            :     {
    1815                 :            :         // Expected output table content.  0 = empty cell
    1816                 :            :         const char* aOutputCheck[][5] = {
    1817                 :            :             { "Sum - Value", "Date", 0, 0, 0 },
    1818                 :            :             { "Name", "2011-01-01", "2011-01-02", "2011-01-03", "Total Result" },
    1819                 :            :             { "Xavior",  0, 0, "45", "45" },
    1820                 :            :             { "Yodel",  0, "20", 0, "20" },
    1821                 :            :             { "Zena",  "30", 0, 0, "30" },
    1822                 :            :             { "Total Result", "30", "20", "45", "95" }
    1823                 :          3 :         };
    1824                 :            : 
    1825         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
    1826 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1827                 :            :     }
    1828                 :            : 
    1829                 :            :     {
    1830                 :            :         const char* aChecks[] = {
    1831                 :            :             "2011-01-01", "2011-01-02", "2011-01-03"
    1832                 :          3 :         };
    1833                 :            : 
    1834                 :            :         // Make sure those cells that contain dates are numeric.
    1835                 :          3 :         SCROW nRow = aOutRange.aStart.Row() + 1;
    1836                 :          3 :         nCol1 = aOutRange.aStart.Col() + 1;
    1837                 :          3 :         nCol2 = nCol1 + 2;
    1838         [ +  + ]:         12 :         for (SCCOL nCol = nCol1; nCol <= nCol2; ++nCol)
    1839                 :            :         {
    1840         [ +  - ]:          9 :             OUString aVal = m_pDoc->GetString(nCol, nRow, 1);
    1841 [ +  - ][ +  - ]:          9 :             CPPUNIT_ASSERT_MESSAGE("Cell value is not as expected.", aVal.equalsAscii(aChecks[nCol-nCol1]));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1842 [ +  - ][ +  - ]:         18 :             CPPUNIT_ASSERT_MESSAGE("This cell contains a date value and is supposed to be numeric.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1843         [ +  - ]:          9 :                                    m_pDoc->HasValueData(nCol, nRow, 1));
    1844                 :          9 :         }
    1845                 :            :     }
    1846                 :            : 
    1847         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    1848                 :            : 
    1849         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    1850         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    1851                 :          3 : }
    1852                 :            : 
    1853                 :          3 : void Test::testPivotTableFilters()
    1854                 :            : {
    1855         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    1856         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    1857                 :            : 
    1858                 :            :     // Dimension definition
    1859                 :            :     DPFieldDef aFields[] = {
    1860                 :            :         { "Name",   sheet::DataPilotFieldOrientation_HIDDEN, 0 },
    1861                 :            :         { "Group1", sheet::DataPilotFieldOrientation_HIDDEN, 0 },
    1862                 :            :         { "Group2", sheet::DataPilotFieldOrientation_PAGE, 0 },
    1863                 :            :         { "Val1",   sheet::DataPilotFieldOrientation_DATA, 0 },
    1864                 :            :         { "Val2",   sheet::DataPilotFieldOrientation_DATA, 0 }
    1865                 :          3 :     };
    1866                 :            : 
    1867                 :            :     // Raw data
    1868                 :            :     const char* aData[][5] = {
    1869                 :            :         { "A", "1", "A", "1", "10" },
    1870                 :            :         { "B", "1", "A", "1", "10" },
    1871                 :            :         { "C", "1", "B", "1", "10" },
    1872                 :            :         { "D", "1", "B", "1", "10" },
    1873                 :            :         { "E", "2", "A", "1", "10" },
    1874                 :            :         { "F", "2", "A", "1", "10" },
    1875                 :            :         { "G", "2", "B", "1", "10" },
    1876                 :            :         { "H", "2", "B", "1", "10" }
    1877                 :          3 :     };
    1878                 :            : 
    1879                 :          3 :     size_t nFieldCount = SAL_N_ELEMENTS(aFields);
    1880                 :          3 :     size_t nDataCount = SAL_N_ELEMENTS(aData);
    1881                 :            : 
    1882         [ +  - ]:          3 :     ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
    1883                 :          3 :     SCROW nRow1 = aSrcRange.aStart.Row(), nRow2 = aSrcRange.aEnd.Row();
    1884                 :          3 :     SCCOL nCol1 = aSrcRange.aStart.Col(), nCol2 = aSrcRange.aEnd.Col();
    1885                 :            : 
    1886                 :            :     ScDPObject* pDPObj = createDPFromRange(
    1887         [ +  - ]:          3 :         m_pDoc, ScRange(nCol1, nRow1, 0, nCol2, nRow2, 0), aFields, nFieldCount, true);
    1888                 :            : 
    1889         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    1890         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    1891 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new datapilot object into document", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1892 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1893         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    1894 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    1895                 :            : 
    1896         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    1897                 :            :     {
    1898                 :            :         // Expected output table content.  0 = empty cell
    1899                 :            :         const char* aOutputCheck[][2] = {
    1900                 :            :             { "Filter", 0 },
    1901                 :            :             { "Group2", "- all -" },
    1902                 :            :             { 0, 0 },
    1903                 :            :             { "Data", 0 },
    1904                 :            :             { "Sum - Val1", "8" },
    1905                 :            :             { "Sum - Val2", "80" }
    1906                 :          3 :         };
    1907                 :            : 
    1908         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (unfiltered)");
    1909 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1910                 :            :     }
    1911                 :            : 
    1912         [ +  - ]:          3 :     AutoCalcSwitch aACSwitch(m_pDoc, true); // turn on auto calculation.
    1913                 :            : 
    1914                 :          3 :     ScAddress aFormulaAddr = aOutRange.aEnd;
    1915         [ +  - ]:          3 :     aFormulaAddr.IncRow(2);
    1916                 :          6 :     m_pDoc->SetString(aFormulaAddr.Col(), aFormulaAddr.Row(), aFormulaAddr.Tab(),
    1917         [ +  - ]:          9 :                       rtl::OUString("=B6"));
    1918         [ +  - ]:          3 :     double fTest = m_pDoc->GetValue(aFormulaAddr);
    1919 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Incorrect formula value that references a cell in the pivot table output.", fTest == 80.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1920                 :            : 
    1921                 :            :     // Set current page of 'Group2' to 'A'.
    1922         [ +  - ]:          3 :     ScDPSaveData aSaveData(*pDPObj->GetSaveData());
    1923                 :            :     ScDPSaveDimension* pDim = aSaveData.GetDimensionByName(
    1924         [ +  - ]:          3 :         OUString("Group2"));
    1925 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Dimension not found", pDim);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1926                 :          3 :     OUString aPage("A");
    1927         [ +  - ]:          3 :     pDim->SetCurrentPage(&aPage);
    1928         [ +  - ]:          3 :     pDPObj->SetSaveData(aSaveData);
    1929         [ +  - ]:          3 :     aOutRange = refresh(pDPObj);
    1930                 :            :     {
    1931                 :            :         // Expected output table content.  0 = empty cell
    1932                 :            :         const char* aOutputCheck[][2] = {
    1933                 :            :             { "Filter", 0 },
    1934                 :            :             { "Group2", "A" },
    1935                 :            :             { 0, 0 },
    1936                 :            :             { "Data", 0 },
    1937                 :            :             { "Sum - Val1", "4" },
    1938                 :            :             { "Sum - Val2", "40" }
    1939                 :          3 :         };
    1940                 :            : 
    1941         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by page)");
    1942 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1943                 :            :     }
    1944                 :            : 
    1945         [ +  - ]:          3 :     fTest = m_pDoc->GetValue(aFormulaAddr);
    1946 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Incorrect formula value that references a cell in the pivot table output.", fTest == 40.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1947                 :            : 
    1948                 :            :     // Set query filter.
    1949         [ +  - ]:          3 :     ScSheetSourceDesc aDesc(*pDPObj->GetSheetDesc());
    1950 [ +  - ][ +  - ]:          3 :     ScQueryParam aQueryParam(aDesc.GetQueryParam());
    1951 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be at least one query entry.", aQueryParam.GetEntryCount() > 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    1952         [ +  - ]:          3 :     ScQueryEntry& rEntry = aQueryParam.GetEntry(0);
    1953                 :          3 :     rEntry.bDoQuery = true;
    1954                 :          3 :     rEntry.nField = 1;  // Group1
    1955         [ +  - ]:          3 :     rEntry.GetQueryItem().mfVal = 1;
    1956         [ +  - ]:          3 :     aDesc.SetQueryParam(aQueryParam);
    1957         [ +  - ]:          3 :     pDPObj->SetSheetDesc(aDesc);
    1958         [ +  - ]:          3 :     aOutRange = refresh(pDPObj);
    1959                 :            :     {
    1960                 :            :         // Expected output table content.  0 = empty cell
    1961                 :            :         const char* aOutputCheck[][2] = {
    1962                 :            :             { "Filter", 0 },
    1963                 :            :             { "Group2", "A" },
    1964                 :            :             { 0, 0 },
    1965                 :            :             { "Data", 0 },
    1966                 :            :             { "Sum - Val1", "2" },
    1967                 :            :             { "Sum - Val2", "20" }
    1968                 :          3 :         };
    1969                 :            : 
    1970         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output (filtered by query)");
    1971 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1972                 :            :     }
    1973                 :            : 
    1974         [ +  - ]:          3 :     fTest = m_pDoc->GetValue(aFormulaAddr);
    1975 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Incorrect formula value that references a cell in the pivot table output.", fTest == 20.0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1976                 :            : 
    1977         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    1978 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("There shouldn't be any data pilot table stored with the document.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1979         [ +  - ]:          3 :                            pDPs->GetCount() == 0);
    1980                 :            : 
    1981         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    1982 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
         [ +  - ][ +  - ]
                 [ +  - ]
    1983                 :          3 : }
    1984                 :            : 
    1985                 :          3 : void Test::testPivotTableNamedSource()
    1986                 :            : {
    1987         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    1988         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    1989                 :            : 
    1990                 :            :     // Dimension definition
    1991                 :            :     DPFieldDef aFields[] = {
    1992                 :            :         { "Name",  sheet::DataPilotFieldOrientation_ROW, 0 },
    1993                 :            :         { "Group", sheet::DataPilotFieldOrientation_COLUMN, 0 },
    1994                 :            :         { "Score", sheet::DataPilotFieldOrientation_DATA, 0 }
    1995                 :          3 :     };
    1996                 :            : 
    1997                 :            :     // Raw data
    1998                 :            :     const char* aData[][3] = {
    1999                 :            :         { "Andy",    "A", "30" },
    2000                 :            :         { "Bruce",   "A", "20" },
    2001                 :            :         { "Charlie", "B", "45" },
    2002                 :            :         { "David",   "B", "12" },
    2003                 :            :         { "Edward",  "C",  "8" },
    2004                 :            :         { "Frank",   "C", "15" },
    2005                 :          3 :     };
    2006                 :            : 
    2007                 :          3 :     size_t nFieldCount = SAL_N_ELEMENTS(aFields);
    2008                 :          3 :     size_t nDataCount = SAL_N_ELEMENTS(aData);
    2009                 :            : 
    2010                 :            :     // Insert the raw data.
    2011         [ +  - ]:          3 :     ScRange aSrcRange = insertDPSourceData(m_pDoc, aFields, nFieldCount, aData, nDataCount);
    2012                 :          3 :     rtl::OUString aRangeStr;
    2013         [ +  - ]:          3 :     aSrcRange.Format(aRangeStr, SCR_ABS_3D, m_pDoc);
    2014                 :            : 
    2015                 :            :     // Name this range.
    2016                 :          3 :     rtl::OUString aRangeName("MyData");
    2017         [ +  - ]:          3 :     ScRangeName* pNames = m_pDoc->GetRangeName();
    2018 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to get global range name container.", pNames);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2019                 :            :     ScRangeData* pName = new ScRangeData(
    2020 [ +  - ][ +  - ]:          3 :         m_pDoc, aRangeName, aRangeStr);
         [ +  - ][ +  - ]
    2021         [ +  - ]:          3 :     bool bSuccess = pNames->insert(pName);
    2022 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to insert a new name.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2023                 :            : 
    2024         [ +  - ]:          3 :     ScSheetSourceDesc aSheetDesc(m_pDoc);
    2025         [ +  - ]:          3 :     aSheetDesc.SetRangeName(aRangeName);
    2026         [ +  - ]:          3 :     ScDPObject* pDPObj = createDPFromSourceDesc(m_pDoc, aSheetDesc, aFields, nFieldCount, false);
    2027 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to create a new pivot table object.", pDPObj);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2028                 :            : 
    2029         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2030         [ +  - ]:          3 :     bSuccess = pDPs->InsertNewTable(pDPObj);
    2031 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2032 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2033         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    2034 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2035                 :            : 
    2036         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    2037                 :            :     {
    2038                 :            :         // Expected output table content.  0 = empty cell
    2039                 :            :         const char* aOutputCheck[][5] = {
    2040                 :            :             { "Sum - Score", "Group", 0, 0, 0 },
    2041                 :            :             { "Name", "A", "B", "C", "Total Result" },
    2042                 :            :             { "Andy", "30", 0, 0, "30" },
    2043                 :            :             { "Bruce", "20", 0, 0, "20" },
    2044                 :            :             { "Charlie", 0, "45", 0, "45" },
    2045                 :            :             { "David", 0, "12", 0, "12" },
    2046                 :            :             { "Edward", 0, 0, "8", "8" },
    2047                 :            :             { "Frank", 0, 0, "15", "15" },
    2048                 :            :             { "Total Result", "50", "57", "23", "130" }
    2049                 :          3 :         };
    2050                 :            : 
    2051         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<5>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
    2052 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2053                 :            :     }
    2054                 :            : 
    2055 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("There should be one named range data cache.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    2056         [ +  - ]:          3 :                            pDPs->GetNameCaches().size() == 1 && pDPs->GetSheetCaches().size() == 0);
    2057                 :            : 
    2058                 :            :     // Move the table with pivot table to the left of the source data sheet.
    2059         [ +  - ]:          3 :     m_pDoc->MoveTab(1, 0);
    2060                 :          3 :     rtl::OUString aTabName;
    2061         [ +  - ]:          3 :     m_pDoc->GetName(0, aTabName);
    2062 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE( "Wrong sheet name.", aTabName == "Table" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2063 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Pivot table output is on the wrong sheet!",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2064         [ +  - ]:          3 :                            pDPObj->GetOutRange().aStart.Tab() == 0);
    2065                 :            : 
    2066 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Moving the pivot table to another sheet shouldn't have changed the cache state.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    2067         [ +  - ]:          3 :                            pDPs->GetNameCaches().size() == 1 && pDPs->GetSheetCaches().size() == 0);
    2068                 :            : 
    2069                 :          3 :     const ScSheetSourceDesc* pDesc = pDPObj->GetSheetDesc();
    2070 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Sheet source description doesn't exist.", pDesc);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2071 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Named source range has been altered unexpectedly!",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2072         [ +  - ]:          3 :                            pDesc->GetRangeName().equals(aRangeName));
    2073                 :            : 
    2074 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache should exist.", pDPs->GetNameCaches().hasCache(aRangeName));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2075                 :            : 
    2076         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2077 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be no more tables.", pDPs->GetCount() == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2078 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2079         [ +  - ]:          3 :                            pDPs->GetNameCaches().size() == 0);
    2080                 :            : 
    2081         [ +  - ]:          3 :     pNames->clear();
    2082         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2083 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2084                 :          3 : }
    2085                 :            : 
    2086                 :          3 : void Test::testPivotTableCache()
    2087                 :            : {
    2088         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2089                 :            : 
    2090                 :            :     // Raw data
    2091                 :            :     const char* aData[][3] = {
    2092                 :            :         { "F1", "F2", "F3" },
    2093                 :            :         { "Z",  "A", "30" },
    2094                 :            :         { "R",  "A", "20" },
    2095                 :            :         { "A",  "B", "45" },
    2096                 :            :         { "F",  "B", "12" },
    2097                 :            :         { "Y",  "C",  "8" },
    2098                 :            :         { "12", "C", "15" },
    2099                 :          3 :     };
    2100                 :            : 
    2101                 :          3 :     ScAddress aPos(1,1,0);
    2102         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2103 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2104                 :            : 
    2105         [ +  - ]:          3 :     ScDPCache aCache(m_pDoc);
    2106         [ +  - ]:          3 :     aCache.InitFromDoc(m_pDoc, aDataRange);
    2107         [ +  - ]:          3 :     long nDimCount = aCache.GetColumnCount();
    2108 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension count.", nDimCount == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2109         [ +  - ]:          3 :     rtl::OUString aDimName = aCache.GetDimensionName(0);
    2110 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension name", aDimName.equalsAscii("F1"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2111         [ +  - ]:          3 :     aDimName = aCache.GetDimensionName(1);
    2112 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension name", aDimName.equalsAscii("F2"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2113         [ +  - ]:          3 :     aDimName = aCache.GetDimensionName(2);
    2114 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension name", aDimName.equalsAscii("F3"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2115                 :            : 
    2116                 :            :     // In each dimension, member ID values also represent their sort order (in
    2117                 :            :     // source dimensions only, not in group dimensions). Value items are
    2118                 :            :     // sorted before string ones. Also, no duplicate dimension members should
    2119                 :            :     // exist.
    2120                 :            : 
    2121                 :            :     // Dimension 0 - a mix of strings and values.
    2122         [ +  - ]:          3 :     long nMemCount = aCache.GetDimMemberCount(0);
    2123 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension member count", nMemCount == 6);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2124         [ +  - ]:          3 :     const ScDPItemData* pItem = aCache.GetItemDataById(0, 0);
    2125 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2126                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2127         [ +  - ]:          3 :                            pItem->GetValue() == 12);
    2128         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(0, 1);
    2129 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2130                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2131         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("A"));
    2132         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(0, 2);
    2133 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2134                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2135         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("F"));
    2136         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(0, 3);
    2137 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2138                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2139         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("R"));
    2140         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(0, 4);
    2141 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2142                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2143         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("Y"));
    2144         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(0, 5);
    2145 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2146                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2147         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("Z"));
    2148         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(0, 6);
    2149 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", !pItem);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2150                 :            : 
    2151                 :            :     // Dimension 1 - duplicate values in source.
    2152         [ +  - ]:          3 :     nMemCount = aCache.GetDimMemberCount(1);
    2153 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension member count", nMemCount == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2154         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(1, 0);
    2155 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2156                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2157         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("A"));
    2158         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(1, 1);
    2159 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2160                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2161         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("B"));
    2162         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(1, 2);
    2163 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    2164                 :            :                            pItem->GetType() == ScDPItemData::String &&
    2165         [ +  - ]:          3 :                            pItem->GetString().equalsAscii("C"));
    2166         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(1, 3);
    2167 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", !pItem);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2168                 :            : 
    2169                 :            :     // Dimension 2 - values only.
    2170         [ +  - ]:          3 :     nMemCount = aCache.GetDimMemberCount(2);
    2171 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong dimension member count", nMemCount == 6);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2172         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 0);
    2173 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2174                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2175         [ +  - ]:          3 :                            pItem->GetValue() == 8);
    2176         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 1);
    2177 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2178                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2179         [ +  - ]:          3 :                            pItem->GetValue() == 12);
    2180         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 2);
    2181 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2182                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2183         [ +  - ]:          3 :                            pItem->GetValue() == 15);
    2184         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 3);
    2185 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2186                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2187         [ +  - ]:          3 :                            pItem->GetValue() == 20);
    2188         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 4);
    2189 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2190                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2191         [ +  - ]:          3 :                            pItem->GetValue() == 30);
    2192         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 5);
    2193 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", pItem &&
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
                 [ +  - ]
    2194                 :            :                            pItem->GetType() == ScDPItemData::Value &&
    2195         [ +  - ]:          3 :                            pItem->GetValue() == 45);
    2196         [ +  - ]:          3 :     pItem = aCache.GetItemDataById(2, 6);
    2197 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("wrong item value", !pItem);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2198                 :            : 
    2199                 :            :     {
    2200                 :            :         // Check the integrity of the source data.
    2201         [ +  - ]:          3 :         ScDPItemData aTest;
    2202                 :            :         long nDim;
    2203                 :            : 
    2204                 :            :         {
    2205                 :            :             // Dimension 0: Z, R, A, F, Y, 12
    2206                 :          3 :             nDim = 0;
    2207                 :          3 :             const char* aChecks[] = { "Z", "R", "A", "F", "Y" };
    2208         [ +  + ]:         18 :             for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
    2209                 :            :             {
    2210 [ +  - ][ +  - ]:         15 :                 pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, i, false));
    2211         [ +  - ]:         15 :                 aTest.SetString(rtl::OUString::createFromAscii(aChecks[i]));
    2212 [ +  - ][ +  - ]:         15 :                 CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2213                 :            :             }
    2214                 :            : 
    2215 [ +  - ][ +  - ]:          3 :             pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, 5, false));
    2216         [ +  - ]:          3 :             aTest.SetValue(12);
    2217 [ +  - ][ +  - ]:          3 :             CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    2218                 :            :         }
    2219                 :            : 
    2220                 :            :         {
    2221                 :            :             // Dimension 1: A, A, B, B, C, C
    2222                 :          3 :             nDim = 1;
    2223                 :          3 :             const char* aChecks[] = { "A", "A", "B", "B", "C", "C" };
    2224         [ +  + ]:         21 :             for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
    2225                 :            :             {
    2226 [ +  - ][ +  - ]:         18 :                 pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, i, false));
    2227         [ +  - ]:         18 :                 aTest.SetString(rtl::OUString::createFromAscii(aChecks[i]));
    2228 [ +  - ][ +  - ]:         18 :                 CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2229                 :            :             }
    2230                 :            :         }
    2231                 :            : 
    2232                 :            :         {
    2233                 :            :             // Dimension 2: 30, 20, 45, 12, 8, 15
    2234                 :          3 :             nDim = 2;
    2235                 :          3 :             double aChecks[] = { 30, 20, 45, 12, 8, 15 };
    2236         [ +  + ]:         21 :             for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
    2237                 :            :             {
    2238 [ +  - ][ +  - ]:         18 :                 pItem = aCache.GetItemDataById(nDim, aCache.GetItemDataId(nDim, i, false));
    2239         [ +  - ]:         18 :                 aTest.SetValue(aChecks[i]);
    2240 [ +  - ][ +  - ]:         18 :                 CPPUNIT_ASSERT_MESSAGE("wrong data value", pItem && *pItem == aTest);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    2241                 :            :             }
    2242         [ +  - ]:          3 :         }
    2243                 :            :     }
    2244                 :            : 
    2245 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2246                 :          3 : }
    2247                 :            : 
    2248                 :          3 : void Test::testPivotTableDuplicateDataFields()
    2249                 :            : {
    2250         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2251         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2252                 :            : 
    2253                 :            :     // Raw data
    2254                 :            :     const char* aData[][2] = {
    2255                 :            :         { "Name", "Value" },
    2256                 :            :         { "A",       "45" },
    2257                 :            :         { "A",        "5" },
    2258                 :            :         { "A",       "41" },
    2259                 :            :         { "A",       "49" },
    2260                 :            :         { "A",        "4" },
    2261                 :            :         { "B",       "33" },
    2262                 :            :         { "B",       "84" },
    2263                 :            :         { "B",       "74" },
    2264                 :            :         { "B",        "8" },
    2265                 :            :         { "B",       "68" }
    2266                 :          3 :     };
    2267                 :            : 
    2268                 :            :     // Dimension definition
    2269                 :            :     DPFieldDef aFields[] = {
    2270                 :            :         { "Name",  sheet::DataPilotFieldOrientation_ROW, 0 },
    2271                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2272                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_COUNT }
    2273                 :          3 :     };
    2274                 :            : 
    2275                 :          3 :     ScAddress aPos(2,2,0);
    2276         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2277 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2278                 :            : 
    2279                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2280         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2281                 :            : 
    2282         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2283         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2284                 :            : 
    2285 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2286 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
                 [ +  - ]
    2287         [ +  - ]:          3 :                            pDPs->GetCount(), static_cast<size_t>(1));
    2288 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2289                 :            : 
    2290         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    2291                 :            :     {
    2292                 :            :         // Expected output table content.  0 = empty cell
    2293                 :            :         const char* aOutputCheck[][3] = {
    2294                 :            :             { "Name", "Data", 0 },
    2295                 :            :             { "A", "Sum - Value", "144" },
    2296                 :            :             { 0, "Count - Value", "5" },
    2297                 :            :             { "B", "Sum - Value", "267" },
    2298                 :            :             { 0, "Count - Value", "5" },
    2299                 :            :             { "Total Sum - Value", 0, "411" },
    2300                 :            :             { "Total Count - Value", 0, "10" },
    2301                 :          3 :         };
    2302                 :            : 
    2303         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
    2304 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2305                 :            :     }
    2306                 :            : 
    2307                 :            :     // Move the data layout dimension from row to column.
    2308                 :          3 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2309 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No save data!?", pSaveData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2310         [ +  - ]:          3 :     ScDPSaveDimension* pDataLayout = pSaveData->GetDataLayoutDimension();
    2311 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No data layout dimension.", pDataLayout);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2312         [ +  - ]:          3 :     pDataLayout->SetOrientation(sheet::DataPilotFieldOrientation_COLUMN);
    2313         [ +  - ]:          3 :     pDPObj->SetSaveData(*pSaveData);
    2314                 :            : 
    2315                 :            :     // Refresh the table output.
    2316         [ +  - ]:          3 :     aOutRange = refresh(pDPObj);
    2317                 :            :     {
    2318                 :            :         // Expected output table content.  0 = empty cell
    2319                 :            :         const char* aOutputCheck[][3] = {
    2320                 :            :             { 0, "Data", 0 },
    2321                 :            :             { "Name", "Sum - Value", "Count - Value" },
    2322                 :            :             { "A", "144", "5" },
    2323                 :            :             { "B", "267", "5" },
    2324                 :            :             { "Total Result", "411", "10" }
    2325                 :          3 :         };
    2326                 :            : 
    2327         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "DataPilot table output");
    2328 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2329                 :            :     }
    2330                 :            : 
    2331         [ +  - ]:          3 :     ScPivotParam aParam;
    2332         [ +  - ]:          3 :     pDPObj->FillLabelData(aParam);
    2333 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be exactly 4 labels (2 original, 1 data layout, and 1 duplicate dimensions).",
         [ +  - ][ +  - ]
    2334         [ +  - ]:          3 :                            aParam.maLabelArray.size(), static_cast<size_t>(4));
    2335                 :            : 
    2336         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2337 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2338 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2339         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2340                 :            : 
    2341         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2342 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2343                 :          3 : }
    2344                 :            : 
    2345                 :          3 : void Test::testPivotTableNormalGrouping()
    2346                 :            : {
    2347         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2348         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2349                 :            : 
    2350                 :            :     // Raw data
    2351                 :            :     const char* aData[][2] = {
    2352                 :            :         { "Name", "Value" },
    2353                 :            :         { "A", "1" },
    2354                 :            :         { "B", "2" },
    2355                 :            :         { "C", "3" },
    2356                 :            :         { "D", "4" },
    2357                 :            :         { "E", "5" },
    2358                 :            :         { "F", "6" },
    2359                 :            :         { "G", "7" }
    2360                 :          3 :     };
    2361                 :            : 
    2362                 :            :     // Dimension definition
    2363                 :            :     DPFieldDef aFields[] = {
    2364                 :            :         { "Name",  sheet::DataPilotFieldOrientation_ROW, 0 },
    2365                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2366                 :          3 :     };
    2367                 :            : 
    2368                 :          3 :     ScAddress aPos(1,1,0);
    2369         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2370 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2371                 :            : 
    2372                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2373         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2374                 :            : 
    2375         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2376         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2377                 :            : 
    2378 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2379 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
                 [ +  - ]
    2380         [ +  - ]:          3 :                            pDPs->GetCount(), static_cast<size_t>(1));
    2381 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2382                 :            : 
    2383         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    2384                 :            :     {
    2385                 :            :         // Expected output table content.  0 = empty cell
    2386                 :            :         const char* aOutputCheck[][2] = {
    2387                 :            :             { "Name", 0 },
    2388                 :            :             { "A", "1" },
    2389                 :            :             { "B", "2" },
    2390                 :            :             { "C", "3" },
    2391                 :            :             { "D", "4" },
    2392                 :            :             { "E", "5" },
    2393                 :            :             { "F", "6" },
    2394                 :            :             { "G", "7" },
    2395                 :            :             { "Total Result", "28" }
    2396                 :          3 :         };
    2397                 :            : 
    2398         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Initial output without grouping");
    2399 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2400                 :            :     }
    2401                 :            : 
    2402                 :          3 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2403 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No save data !?", pSaveData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2404         [ +  - ]:          3 :     ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();
    2405 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to create dimension data.", pDimData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2406                 :            : 
    2407                 :          3 :     rtl::OUString aGroupPrefix("Group");
    2408                 :          3 :     rtl::OUString aBaseDimName("Name");
    2409                 :            :     rtl::OUString aGroupDimName =
    2410         [ +  - ]:          3 :         pDimData->CreateGroupDimName(aBaseDimName, *pDPObj, false, NULL);
    2411                 :            : 
    2412                 :            :     {
    2413                 :            :         // Group A, B and C together.
    2414         [ +  - ]:          3 :         ScDPSaveGroupDimension aGroupDim(aBaseDimName, aGroupDimName);
    2415         [ +  - ]:          3 :         rtl::OUString aGroupName = aGroupDim.CreateGroupName(aGroupPrefix);
    2416 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Unexpected group name", aGroupName.equalsAscii("Group1"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2417                 :            : 
    2418         [ +  - ]:          3 :         ScDPSaveGroupItem aGroup(aGroupName);
    2419         [ +  - ]:          3 :         aGroup.AddElement(rtl::OUString("A"));
    2420         [ +  - ]:          3 :         aGroup.AddElement(rtl::OUString("B"));
    2421         [ +  - ]:          3 :         aGroup.AddElement(rtl::OUString("C"));
    2422         [ +  - ]:          3 :         aGroupDim.AddGroupItem(aGroup);
    2423         [ +  - ]:          3 :         pDimData->AddGroupDimension(aGroupDim);
    2424                 :            : 
    2425         [ +  - ]:          3 :         ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aGroupDimName);
    2426         [ +  - ]:          3 :         pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
    2427 [ +  - ][ +  - ]:          3 :         pSaveData->SetPosition(pDim, 0); // Set it before the base dimension.
                 [ +  - ]
    2428                 :            :     }
    2429                 :            : 
    2430         [ +  - ]:          3 :     pDPObj->SetSaveData(*pSaveData);
    2431         [ +  - ]:          3 :     aOutRange = refreshGroups(pDPs, pDPObj);
    2432                 :            :     {
    2433                 :            :         // Expected output table content.  0 = empty cell
    2434                 :            :         const char* aOutputCheck[][3] = {
    2435                 :            :             { "Name2", "Name", 0 },
    2436                 :            :             { "D", "D", "4" },
    2437                 :            :             { "E", "E", "5" },
    2438                 :            :             { "F", "F", "6" },
    2439                 :            :             { "G", "G", "7" },
    2440                 :            :             { "Group1", "A", "1" },
    2441                 :            :             { 0,        "B", "2" },
    2442                 :            :             { 0,        "C", "3" },
    2443                 :            :             { "Total Result", 0, "28" }
    2444                 :          3 :         };
    2445                 :            : 
    2446         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "A, B, C grouped by Group1.");
    2447 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2448                 :            :     }
    2449                 :            : 
    2450                 :          3 :     pSaveData = pDPObj->GetSaveData();
    2451         [ +  - ]:          3 :     pDimData = pSaveData->GetDimensionData();
    2452                 :            : 
    2453                 :            :     {
    2454                 :            :         // Group D, E, F together.
    2455         [ +  - ]:          3 :         ScDPSaveGroupDimension* pGroupDim = pDimData->GetGroupDimAccForBase(aBaseDimName);
    2456 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("There should be an existing group dimension.", pGroupDim);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2457         [ +  - ]:          3 :         rtl::OUString aGroupName = pGroupDim->CreateGroupName(aGroupPrefix);
    2458 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Unexpected group name", aGroupName.equalsAscii("Group2"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2459                 :            : 
    2460         [ +  - ]:          3 :         ScDPSaveGroupItem aGroup(aGroupName);
    2461         [ +  - ]:          3 :         aGroup.AddElement(rtl::OUString("D"));
    2462         [ +  - ]:          3 :         aGroup.AddElement(rtl::OUString("E"));
    2463         [ +  - ]:          3 :         aGroup.AddElement(rtl::OUString("F"));
    2464 [ +  - ][ +  - ]:          3 :         pGroupDim->AddGroupItem(aGroup);
    2465                 :            :     }
    2466                 :            : 
    2467         [ +  - ]:          3 :     pDPObj->SetSaveData(*pSaveData);
    2468         [ +  - ]:          3 :     aOutRange = refreshGroups(pDPs, pDPObj);
    2469                 :            :     {
    2470                 :            :         // Expected output table content.  0 = empty cell
    2471                 :            :         const char* aOutputCheck[][3] = {
    2472                 :            :             { "Name2", "Name", 0 },
    2473                 :            :             { "G", "G", "7" },
    2474                 :            :             { "Group1", "A", "1" },
    2475                 :            :             { 0,        "B", "2" },
    2476                 :            :             { 0,        "C", "3" },
    2477                 :            :             { "Group2", "D", "4" },
    2478                 :            :             { 0,        "E", "5" },
    2479                 :            :             { 0,        "F", "6" },
    2480                 :            :             { "Total Result", 0, "28" }
    2481                 :          3 :         };
    2482                 :            : 
    2483         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<3>(m_pDoc, aOutRange, aOutputCheck, "D, E, F grouped by Group2.");
    2484 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2485                 :            :     }
    2486                 :            : 
    2487         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2488 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2489 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2490         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2491                 :            : 
    2492         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2493         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2494                 :          3 : }
    2495                 :            : 
    2496                 :          3 : void Test::testPivotTableNumberGrouping()
    2497                 :            : {
    2498         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2499         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2500                 :            : 
    2501                 :            :     // Raw data
    2502                 :            :     const char* aData[][2] = {
    2503                 :            :         { "Order", "Score" },
    2504                 :            :         { "43", "171" },
    2505                 :            :         { "18", "20"  },
    2506                 :            :         { "69", "159" },
    2507                 :            :         { "95", "19"  },
    2508                 :            :         { "96", "163" },
    2509                 :            :         { "46", "70"  },
    2510                 :            :         { "22", "36"  },
    2511                 :            :         { "81", "49"  },
    2512                 :            :         { "54", "61"  },
    2513                 :            :         { "39", "62"  },
    2514                 :            :         { "86", "17"  },
    2515                 :            :         { "34", "0"   },
    2516                 :            :         { "30", "25"  },
    2517                 :            :         { "24", "103" },
    2518                 :            :         { "16", "59"  },
    2519                 :            :         { "24", "119" },
    2520                 :            :         { "15", "86"  },
    2521                 :            :         { "69", "170" }
    2522                 :          3 :     };
    2523                 :            : 
    2524                 :            :     // Dimension definition
    2525                 :            :     DPFieldDef aFields[] = {
    2526                 :            :         { "Order", sheet::DataPilotFieldOrientation_ROW, 0 },
    2527                 :            :         { "Score", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2528                 :          3 :     };
    2529                 :            : 
    2530                 :          3 :     ScAddress aPos(1,1,0);
    2531         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2532 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2533                 :            : 
    2534                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2535         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2536                 :            : 
    2537         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2538         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2539                 :            : 
    2540 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2541 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
                 [ +  - ]
    2542         [ +  - ]:          3 :                            pDPs->GetCount(), static_cast<size_t>(1));
    2543 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2544                 :            : 
    2545                 :          3 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2546 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No save data !?", pSaveData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2547         [ +  - ]:          3 :     ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();
    2548 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No dimension data !?", pDimData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2549                 :            : 
    2550                 :            :     {
    2551         [ +  - ]:          3 :         ScDPNumGroupInfo aInfo;
    2552                 :          3 :         aInfo.mbEnable = true;
    2553                 :          3 :         aInfo.mbAutoStart = false;
    2554                 :          3 :         aInfo.mbAutoEnd = false;
    2555                 :          3 :         aInfo.mbDateValues = false;
    2556                 :          3 :         aInfo.mbIntegerOnly = true;
    2557                 :          3 :         aInfo.mfStart = 30;
    2558                 :          3 :         aInfo.mfEnd = 60;
    2559                 :          3 :         aInfo.mfStep = 10;
    2560         [ +  - ]:          3 :         ScDPSaveNumGroupDimension aGroup(rtl::OUString("Order"), aInfo);
    2561 [ +  - ][ +  - ]:          3 :         pDimData->AddNumGroupDimension(aGroup);
    2562                 :            :     }
    2563                 :            : 
    2564         [ +  - ]:          3 :     pDPObj->SetSaveData(*pSaveData);
    2565         [ +  - ]:          3 :     ScRange aOutRange = refreshGroups(pDPs, pDPObj);
    2566                 :            :     {
    2567                 :            :         // Expected output table content.  0 = empty cell
    2568                 :            :         const char* aOutputCheck[][2] = {
    2569                 :            :             { "Order", 0 },
    2570                 :            :             { "<30",   "423" },
    2571                 :            :             { "30-39", "87"  },
    2572                 :            :             { "40-49", "241" },
    2573                 :            :             { "50-60", "61"  },
    2574                 :            :             { ">60",   "577" },
    2575                 :            :             { "Total Result", "1389" }
    2576                 :          3 :         };
    2577                 :            : 
    2578         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Order grouped by numbers");
    2579 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2580                 :            :     }
    2581                 :            : 
    2582         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2583 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2584 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2585         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2586                 :            : 
    2587         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2588         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2589                 :          3 : }
    2590                 :            : 
    2591                 :          3 : void Test::testPivotTableDateGrouping()
    2592                 :            : {
    2593         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2594         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2595                 :            : 
    2596                 :            :     // Raw data
    2597                 :            :     const char* aData[][2] = {
    2598                 :            :         { "Date", "Value" },
    2599                 :            :         { "2011-01-01", "1" },
    2600                 :            :         { "2011-03-02", "2" },
    2601                 :            :         { "2012-01-04", "3" },
    2602                 :            :         { "2012-02-23", "4" },
    2603                 :            :         { "2012-02-24", "5" },
    2604                 :            :         { "2012-03-15", "6" },
    2605                 :            :         { "2011-09-03", "7" },
    2606                 :            :         { "2012-12-25", "8" }
    2607                 :          3 :     };
    2608                 :            : 
    2609                 :            :     // Dimension definition
    2610                 :            :     DPFieldDef aFields[] = {
    2611                 :            :         { "Date", sheet::DataPilotFieldOrientation_ROW, 0 },
    2612                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2613                 :          3 :     };
    2614                 :            : 
    2615                 :          3 :     ScAddress aPos(1,1,0);
    2616         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2617 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2618                 :            : 
    2619                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2620         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2621                 :            : 
    2622         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2623         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2624                 :            : 
    2625 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2626 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2627         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    2628 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2629                 :            : 
    2630                 :          3 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2631 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No save data !?", pSaveData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2632         [ +  - ]:          3 :     ScDPDimensionSaveData* pDimData = pSaveData->GetDimensionData();
    2633 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No dimension data !?", pDimData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2634                 :            : 
    2635                 :          3 :     rtl::OUString aBaseDimName("Date");
    2636                 :            : 
    2637         [ +  - ]:          3 :     ScDPNumGroupInfo aInfo;
    2638                 :          3 :     aInfo.mbEnable = true;
    2639                 :          3 :     aInfo.mbAutoStart = true;
    2640                 :          3 :     aInfo.mbAutoEnd = true;
    2641                 :            :     {
    2642                 :            :         // Turn the Date dimension into months.  The first of the date
    2643                 :            :         // dimensions is always a number-group dimension which replaces the
    2644                 :            :         // original dimension.
    2645         [ +  - ]:          3 :         ScDPSaveNumGroupDimension aGroup(aBaseDimName, aInfo, sheet::DataPilotFieldGroupBy::MONTHS);
    2646 [ +  - ][ +  - ]:          3 :         pDimData->AddNumGroupDimension(aGroup);
    2647                 :            :     }
    2648                 :            : 
    2649                 :            :     {
    2650                 :            :         // Add quarter dimension.  This will be an additional dimension.
    2651                 :            :         rtl::OUString aGroupDimName =
    2652                 :            :             pDimData->CreateDateGroupDimName(
    2653         [ +  - ]:          3 :                 sheet::DataPilotFieldGroupBy::QUARTERS, *pDPObj, true, NULL);
    2654         [ +  - ]:          3 :         ScDPSaveGroupDimension aGroupDim(aBaseDimName, aGroupDimName);
    2655         [ +  - ]:          3 :         aGroupDim.SetDateInfo(aInfo, sheet::DataPilotFieldGroupBy::QUARTERS);
    2656         [ +  - ]:          3 :         pDimData->AddGroupDimension(aGroupDim);
    2657                 :            : 
    2658                 :            :         // Set orientation.
    2659         [ +  - ]:          3 :         ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aGroupDimName);
    2660         [ +  - ]:          3 :         pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
    2661 [ +  - ][ +  - ]:          3 :         pSaveData->SetPosition(pDim, 0); // set it to the left end.
    2662                 :            :     }
    2663                 :            : 
    2664                 :            :     {
    2665                 :            :         // Add year dimension.  This is a new dimension also.
    2666                 :            :         rtl::OUString aGroupDimName =
    2667                 :            :             pDimData->CreateDateGroupDimName(
    2668         [ +  - ]:          3 :                 sheet::DataPilotFieldGroupBy::YEARS, *pDPObj, true, NULL);
    2669         [ +  - ]:          3 :         ScDPSaveGroupDimension aGroupDim(aBaseDimName, aGroupDimName);
    2670         [ +  - ]:          3 :         aGroupDim.SetDateInfo(aInfo, sheet::DataPilotFieldGroupBy::YEARS);
    2671         [ +  - ]:          3 :         pDimData->AddGroupDimension(aGroupDim);
    2672                 :            : 
    2673                 :            :         // Set orientation.
    2674         [ +  - ]:          3 :         ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(aGroupDimName);
    2675         [ +  - ]:          3 :         pDim->SetOrientation(sheet::DataPilotFieldOrientation_ROW);
    2676 [ +  - ][ +  - ]:          3 :         pSaveData->SetPosition(pDim, 0); // set it to the left end.
    2677                 :            :     }
    2678                 :            : 
    2679         [ +  - ]:          3 :     pDPObj->SetSaveData(*pSaveData);
    2680         [ +  - ]:          3 :     ScRange aOutRange = refreshGroups(pDPs, pDPObj);
    2681                 :            :     {
    2682                 :            :         // Expected output table content.  0 = empty cell
    2683                 :            :         const char* aOutputCheck[][4] = {
    2684                 :            :             { "Years", "Quarters", "Date", 0 },
    2685                 :            :             { "2011", "Q1", "Jan", "1" },
    2686                 :            :             { 0, 0,         "Mar", "2" },
    2687                 :            :             { 0,      "Q3", "Sep", "7" },
    2688                 :            :             { "2012", "Q1", "Jan", "3" },
    2689                 :            :             { 0, 0,         "Feb", "9" },
    2690                 :            :             { 0, 0,         "Mar", "6" },
    2691                 :            :             { 0,      "Q4", "Dec", "8" },
    2692                 :            :             { "Total Result", 0, 0, "36" },
    2693                 :          3 :         };
    2694                 :            : 
    2695         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<4>(m_pDoc, aOutRange, aOutputCheck, "Years, quarters and months date groups.");
    2696 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2697                 :            :     }
    2698                 :            : 
    2699                 :            :     {
    2700                 :            :         // Let's hide year 2012.
    2701                 :          3 :         pSaveData = pDPObj->GetSaveData();
    2702         [ +  - ]:          3 :         ScDPSaveDimension* pDim = pSaveData->GetDimensionByName(rtl::OUString("Years"));
    2703 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Years dimension should exist.", pDim);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2704         [ +  - ]:          3 :         ScDPSaveMember* pMem = pDim->GetMemberByName(rtl::OUString("2012"));
    2705 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Member should exist.", pMem);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2706         [ +  - ]:          3 :         pMem->SetIsVisible(false);
    2707                 :            :     }
    2708         [ +  - ]:          3 :     pDPObj->SetSaveData(*pSaveData);
    2709         [ +  - ]:          3 :     pDPObj->ReloadGroupTableData();
    2710         [ +  - ]:          3 :     pDPObj->InvalidateData();
    2711                 :            : 
    2712         [ +  - ]:          3 :     aOutRange = refresh(pDPObj);
    2713                 :            :     {
    2714                 :            :         // Expected output table content.  0 = empty cell
    2715                 :            :         const char* aOutputCheck[][4] = {
    2716                 :            :             { "Years", "Quarters", "Date", 0 },
    2717                 :            :             { "2011", "Q1", "Jan", "1" },
    2718                 :            :             { 0, 0,         "Mar", "2" },
    2719                 :            :             { 0,      "Q3", "Sep", "7" },
    2720                 :            :             { "Total Result", 0, 0, "10" },
    2721                 :          3 :         };
    2722                 :            : 
    2723         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<4>(m_pDoc, aOutRange, aOutputCheck, "Year 2012 data now hidden");
    2724 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2725                 :            :     }
    2726                 :            : 
    2727         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2728 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2729 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2730         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2731                 :            : 
    2732         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2733         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2734                 :          3 : }
    2735                 :            : 
    2736                 :          3 : void Test::testPivotTableEmptyRows()
    2737                 :            : {
    2738         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2739         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2740                 :            : 
    2741                 :            :     // Raw data
    2742                 :            :     const char* aData[][2] = {
    2743                 :            :         { "Name", "Value" },
    2744                 :            :         { "A", "1" },
    2745                 :            :         { "B", "2" },
    2746                 :            :         { "C", "3" },
    2747                 :            :         { "D", "4" },
    2748                 :          3 :     };
    2749                 :            : 
    2750                 :            :     // Dimension definition
    2751                 :            :     DPFieldDef aFields[] = {
    2752                 :            :         { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
    2753                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2754                 :          3 :     };
    2755                 :            : 
    2756                 :          3 :     ScAddress aPos(1,1,0);
    2757         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2758 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2759                 :            : 
    2760                 :            :     // Extend the range downward to include some trailing empty rows.
    2761         [ +  - ]:          3 :     aDataRange.aEnd.IncRow(2);
    2762                 :            : 
    2763                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2764         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2765                 :            : 
    2766         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2767         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2768                 :            : 
    2769 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2770 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2771         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    2772 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2773                 :            : 
    2774         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    2775                 :            : 
    2776                 :            :     {
    2777                 :            :         // Expected output table content.  0 = empty cell
    2778                 :            :         const char* aOutputCheck[][2] = {
    2779                 :            :             { "Name", 0 },
    2780                 :            :             { "A", "1" },
    2781                 :            :             { "B", "2" },
    2782                 :            :             { "C", "3" },
    2783                 :            :             { "D", "4" },
    2784                 :            :             { "(empty)", 0 },
    2785                 :            :             { "Total Result", "10" },
    2786                 :          3 :         };
    2787                 :            : 
    2788         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Include empty rows");
    2789 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2790                 :            :     }
    2791                 :            : 
    2792                 :            :     // This time, ignore empty rows.
    2793                 :          3 :     ScDPSaveData* pSaveData = pDPObj->GetSaveData();
    2794 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Save data doesn't exist.", pSaveData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2795         [ +  - ]:          3 :     pSaveData->SetIgnoreEmptyRows(true);
    2796         [ +  - ]:          3 :     pDPObj->ClearTableData();
    2797         [ +  - ]:          3 :     aOutRange = refresh(pDPObj);
    2798                 :            : 
    2799                 :            :     {
    2800                 :            :         // Expected output table content.  0 = empty cell
    2801                 :            :         const char* aOutputCheck[][2] = {
    2802                 :            :             { "Name", 0 },
    2803                 :            :             { "A", "1" },
    2804                 :            :             { "B", "2" },
    2805                 :            :             { "C", "3" },
    2806                 :            :             { "D", "4" },
    2807                 :            :             { "Total Result", "10" },
    2808                 :          3 :         };
    2809                 :            : 
    2810         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Ignore empty rows");
    2811 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2812                 :            :     }
    2813                 :            : 
    2814                 :            :     // Modify the source to remove member 'A', then refresh the table.
    2815         [ +  - ]:          3 :     m_pDoc->SetString(1, 2, 0, "B");
    2816                 :            : 
    2817         [ +  - ]:          3 :     std::set<ScDPObject*> aRefs;
    2818         [ +  - ]:          3 :     sal_uLong nErr = pDPs->ReloadCache(pDPObj, aRefs);
    2819 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to reload cache.", !nErr);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2820 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("There should only be one pivot table linked to this cache.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
                 [ +  - ]
    2821         [ +  - ]:          3 :                            aRefs.size() == 1 && *aRefs.begin() == pDPObj);
    2822                 :            : 
    2823         [ +  - ]:          3 :     pDPObj->ClearTableData();
    2824         [ +  - ]:          3 :     aOutRange = refresh(pDPObj);
    2825                 :            : 
    2826                 :            :     {
    2827                 :            :         // Expected output table content.  0 = empty cell
    2828                 :            :         const char* aOutputCheck[][2] = {
    2829                 :            :             { "Name", 0 },
    2830                 :            :             { "B", "3" },
    2831                 :            :             { "C", "3" },
    2832                 :            :             { "D", "4" },
    2833                 :            :             { "Total Result", "10" },
    2834                 :          3 :         };
    2835                 :            : 
    2836         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Ignore empty rows");
    2837 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2838                 :            :     }
    2839                 :            : 
    2840         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2841 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2842 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2843         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2844                 :            : 
    2845         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2846         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2847                 :          3 : }
    2848                 :            : 
    2849                 :          3 : void Test::testPivotTableTextNumber()
    2850                 :            : {
    2851         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2852         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2853                 :            : 
    2854                 :            :     // Raw data
    2855                 :            :     const char* aData[][2] = {
    2856                 :            :         { "Name", "Value" },
    2857                 :            :         { "0001", "1" },
    2858                 :            :         { "0002", "2" },
    2859                 :            :         { "0003", "3" },
    2860                 :            :         { "0004", "4" },
    2861                 :          3 :     };
    2862                 :            : 
    2863                 :            :     // Dimension definition
    2864                 :            :     DPFieldDef aFields[] = {
    2865                 :            :         { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
    2866                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2867                 :          3 :     };
    2868                 :            : 
    2869                 :            :     // Insert raw data such that the first column values are entered as text.
    2870                 :          3 :     size_t nRowCount = SAL_N_ELEMENTS(aData);
    2871         [ +  + ]:         18 :     for (size_t nRow = 0; nRow < nRowCount; ++nRow)
    2872                 :            :     {
    2873         [ +  - ]:         15 :         ScSetStringParam aParam;
    2874                 :         15 :         aParam.mbDetectNumberFormat = false;
    2875                 :         15 :         aParam.meSetTextNumFormat = ScSetStringParam::Always;
    2876         [ +  - ]:         15 :         m_pDoc->SetString(0, nRow, 0, OUString::createFromAscii(aData[nRow][0]), &aParam);
    2877                 :         15 :         aParam.meSetTextNumFormat = ScSetStringParam::Never;
    2878         [ +  - ]:         15 :         m_pDoc->SetString(1, nRow, 0, OUString::createFromAscii(aData[nRow][1]), &aParam);
    2879                 :            : 
    2880         [ +  + ]:         15 :         if (nRow == 0)
    2881                 :            :             // Don't check the header row.
    2882                 :          3 :             continue;
    2883                 :            : 
    2884                 :            :         // Check the data rows.
    2885 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE("This cell is supposed to be text.", m_pDoc->HasStringData(0, nRow, 0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2886 [ +  - ][ +  - ]:         12 :         CPPUNIT_ASSERT_MESSAGE("This cell is supposed to be numeric.", m_pDoc->HasValueData(1, nRow, 0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2887                 :            :     }
    2888                 :            : 
    2889                 :          3 :     ScRange aDataRange(0, 0, 0, 1, 4, 0);
    2890                 :            : 
    2891                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2892         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2893                 :            : 
    2894         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2895         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2896                 :            : 
    2897 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2898 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2899         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    2900 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2901                 :            : 
    2902         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    2903                 :            : 
    2904                 :            :     {
    2905                 :            :         // Expected output table content.  0 = empty cell
    2906                 :            :         const char* aOutputCheck[][2] = {
    2907                 :            :             { "Name", 0 },
    2908                 :            :             { "0001", "1" },
    2909                 :            :             { "0002", "2" },
    2910                 :            :             { "0003", "3" },
    2911                 :            :             { "0004", "4" },
    2912                 :            :             { "Total Result", "10" },
    2913                 :          3 :         };
    2914                 :            : 
    2915         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Text number field members");
    2916 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2917                 :            :     }
    2918                 :            : 
    2919         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2920 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2921 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2922         [ +  - ]:          3 :                                  pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2923                 :            : 
    2924         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2925         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2926                 :          3 : }
    2927                 :            : 
    2928                 :          3 : void Test::testPivotTableCaseInsensitiveStrings()
    2929                 :            : {
    2930         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    2931         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Table"));
    2932                 :            : 
    2933                 :            :     // Raw data
    2934                 :            :     const char* aData[][2] = {
    2935                 :            :         { "Name", "Value" },
    2936                 :            :         { "A", "1" },
    2937                 :            :         { "a", "2" },
    2938                 :          3 :     };
    2939                 :            : 
    2940                 :            :     // Dimension definition
    2941                 :            :     DPFieldDef aFields[] = {
    2942                 :            :         { "Name", sheet::DataPilotFieldOrientation_ROW, 0 },
    2943                 :            :         { "Value", sheet::DataPilotFieldOrientation_DATA, sheet::GeneralFunction_SUM },
    2944                 :          3 :     };
    2945                 :            : 
    2946                 :          3 :     ScAddress aPos(1,1,0);
    2947         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData(m_pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    2948 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2949                 :            : 
    2950                 :            :     ScDPObject* pDPObj = createDPFromRange(
    2951         [ +  - ]:          3 :         m_pDoc, aDataRange, aFields, SAL_N_ELEMENTS(aFields), false);
    2952                 :            : 
    2953         [ +  - ]:          3 :     ScDPCollection* pDPs = m_pDoc->GetDPCollection();
    2954         [ +  - ]:          3 :     bool bSuccess = pDPs->InsertNewTable(pDPObj);
    2955                 :            : 
    2956 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert a new pivot table object into document.", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2957 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("there should be only one data pilot table.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2958         [ +  - ]:          3 :                            pDPs->GetCount() == 1);
    2959 [ +  - ][ +  - ]:          3 :     pDPObj->SetName(pDPs->CreateNewName());
    2960                 :            : 
    2961         [ +  - ]:          3 :     ScRange aOutRange = refresh(pDPObj);
    2962                 :            : 
    2963                 :            :     {
    2964                 :            :         // Expected output table content.  0 = empty cell
    2965                 :            :         const char* aOutputCheck[][2] = {
    2966                 :            :             { "Name", 0 },
    2967                 :            :             { "A", "3" },
    2968                 :            :             { "Total Result", "3" },
    2969                 :          3 :         };
    2970                 :            : 
    2971         [ +  - ]:          3 :         bSuccess = checkDPTableOutput<2>(m_pDoc, aOutRange, aOutputCheck, "Case insensitive strings");
    2972 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Table output check failed", bSuccess);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    2973                 :            :     }
    2974                 :            : 
    2975         [ +  - ]:          3 :     pDPs->FreeTable(pDPObj);
    2976 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be no more tables.", pDPs->GetCount(), static_cast<size_t>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2977 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There shouldn't be any more cache stored.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2978         [ +  - ]:          3 :                            pDPs->GetSheetCaches().size(), static_cast<size_t>(0));
    2979                 :            : 
    2980         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2981         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    2982                 :          3 : }
    2983                 :            : 
    2984                 :          3 : void Test::testSheetCopy()
    2985                 :            : {
    2986                 :          3 :     OUString aTabName("TestTab");
    2987         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aTabName);
    2988 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("document should have one sheet to begin with.", m_pDoc->GetTableCount() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2989                 :            :     SCROW nRow1, nRow2;
    2990         [ +  - ]:          3 :     bool bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    2991 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    2992                 :            : 
    2993                 :            :     // Copy and test the result.
    2994         [ +  - ]:          3 :     m_pDoc->CopyTab(0, 1);
    2995 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount() == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    2996         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
    2997 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("copied sheet should also have all rows visible as the original.", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    2998         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    2999                 :            : 
    3000         [ +  - ]:          3 :     m_pDoc->SetRowHidden(5, 10, 0, true);
    3001         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    3002 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3003         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(5, 0, &nRow1, &nRow2);
    3004 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3005         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(11, 0, &nRow1, &nRow2);
    3006 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3007                 :            : 
    3008                 :            :     // Copy the sheet once again.
    3009         [ +  - ]:          3 :     m_pDoc->CopyTab(0, 1);
    3010 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount() == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3011         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
    3012 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3013         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(5, 1, &nRow1, &nRow2);
    3014 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3015         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(11, 1, &nRow1, &nRow2);
    3016 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3017         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    3018         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3019                 :          3 : }
    3020                 :            : 
    3021                 :          3 : void Test::testSheetMove()
    3022                 :            : {
    3023                 :          3 :     OUString aTabName("TestTab1");
    3024         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aTabName);
    3025 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("document should have one sheet to begin with.", m_pDoc->GetTableCount(), static_cast<SCTAB>(1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3026                 :            :     SCROW nRow1, nRow2;
    3027         [ +  - ]:          3 :     bool bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    3028 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3029                 :            : 
    3030                 :            :     //test if inserting before another sheet works
    3031         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("TestTab2"));
    3032 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("document should have two sheets", m_pDoc->GetTableCount(), static_cast<SCTAB>(2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3033         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    3034 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3035                 :            : 
    3036                 :            :     // Move and test the result.
    3037         [ +  - ]:          3 :     m_pDoc->MoveTab(0, 1);
    3038 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount(), static_cast<SCTAB>(2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3039         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
    3040 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("copied sheet should also have all rows visible as the original.", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3041                 :          3 :     rtl::OUString aName;
    3042         [ +  - ]:          3 :     m_pDoc->GetName(0, aName);
    3043 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE( "sheets should have changed places", aName == "TestTab1" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3044                 :            : 
    3045         [ +  - ]:          3 :     m_pDoc->SetRowHidden(5, 10, 0, true);
    3046         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    3047 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3048         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(5, 0, &nRow1, &nRow2);
    3049 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3050         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(11, 0, &nRow1, &nRow2);
    3051 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3052                 :            : 
    3053                 :            :     // Move the sheet once again.
    3054         [ +  - ]:          3 :     m_pDoc->MoveTab(1, 0);
    3055 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("document now should have two sheets.", m_pDoc->GetTableCount(), static_cast<SCTAB>(2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3056         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 1, &nRow1, &nRow2);
    3057 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 0 - 4 should be visible", !bHidden && nRow1 == 0 && nRow2 == 4);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3058         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(5, 1, &nRow1, &nRow2);
    3059 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 5 - 10 should be hidden", bHidden && nRow1 == 5 && nRow2 == 10);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3060         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(11, 1, &nRow1, &nRow2);
    3061 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 11 - maxrow should be visible", !bHidden && nRow1 == 11 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3062         [ +  - ]:          3 :     m_pDoc->GetName(0, aName);
    3063 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE( "sheets should have changed places", aName == "TestTab2" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3064         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    3065         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3066                 :          3 : }
    3067                 :            : 
    3068                 :         15 : ScDocShell* findLoadedDocShellByName(const OUString& rName)
    3069                 :            : {
    3070         [ +  - ]:         15 :     TypeId aType(TYPE(ScDocShell));
    3071         [ +  - ]:         15 :     ScDocShell* pShell = static_cast<ScDocShell*>(SfxObjectShell::GetFirst(&aType, false));
    3072         [ +  + ]:        450 :     while (pShell)
    3073                 :            :     {
    3074                 :        444 :         SfxMedium* pMedium = pShell->GetMedium();
    3075         [ +  + ]:        444 :         if (pMedium)
    3076                 :            :         {
    3077         [ +  - ]:         12 :             OUString aName = pMedium->GetName();
    3078         [ +  + ]:         12 :             if (aName.equals(rName))
    3079         [ +  + ]:         12 :                 return pShell;
    3080                 :            :         }
    3081         [ +  - ]:        435 :         pShell = static_cast<ScDocShell*>(SfxObjectShell::GetNext(*pShell, &aType, false));
    3082                 :            :     }
    3083                 :         15 :     return NULL;
    3084                 :            : }
    3085                 :            : 
    3086                 :          6 : ScRange getCachedRange(const ScExternalRefCache::TableTypeRef& pCacheTab)
    3087                 :            : {
    3088                 :          6 :     ScRange aRange;
    3089                 :            : 
    3090         [ +  - ]:          6 :     vector<SCROW> aRows;
    3091         [ +  - ]:          6 :     pCacheTab->getAllRows(aRows);
    3092 [ +  - ][ +  - ]:          6 :     vector<SCROW>::const_iterator itrRow = aRows.begin(), itrRowEnd = aRows.end();
    3093                 :          6 :     bool bFirst = true;
    3094 [ +  - ][ +  - ]:         33 :     for (; itrRow != itrRowEnd; ++itrRow)
                 [ +  + ]
    3095                 :            :     {
    3096         [ +  - ]:         27 :         SCROW nRow = *itrRow;
    3097         [ +  - ]:         27 :         vector<SCCOL> aCols;
    3098         [ +  - ]:         27 :         pCacheTab->getAllCols(nRow, aCols);
    3099 [ +  - ][ +  - ]:         27 :         vector<SCCOL>::const_iterator itrCol = aCols.begin(), itrColEnd = aCols.end();
    3100 [ +  - ][ +  - ]:         81 :         for (; itrCol != itrColEnd; ++itrCol)
                 [ +  + ]
    3101                 :            :         {
    3102         [ +  - ]:         54 :             SCCOL nCol = *itrCol;
    3103         [ +  + ]:         54 :             if (bFirst)
    3104                 :            :             {
    3105                 :          6 :                 aRange.aStart = ScAddress(nCol, nRow, 0);
    3106                 :          6 :                 aRange.aEnd = aRange.aStart;
    3107                 :          6 :                 bFirst = false;
    3108                 :            :             }
    3109                 :            :             else
    3110                 :            :             {
    3111         [ -  + ]:         48 :                 if (nCol < aRange.aStart.Col())
    3112                 :          0 :                     aRange.aStart.SetCol(nCol);
    3113         [ +  + ]:         48 :                 else if (aRange.aEnd.Col() < nCol)
    3114                 :          6 :                     aRange.aEnd.SetCol(nCol);
    3115                 :            : 
    3116         [ -  + ]:         48 :                 if (nRow < aRange.aStart.Row())
    3117                 :          0 :                     aRange.aStart.SetRow(nRow);
    3118         [ +  + ]:         48 :                 else if (aRange.aEnd.Row() < nRow)
    3119                 :         21 :                     aRange.aEnd.SetRow(nRow);
    3120                 :            :             }
    3121                 :            :         }
    3122                 :         27 :     }
    3123                 :          6 :     return aRange;
    3124                 :            : }
    3125                 :            : 
    3126                 :          3 : void Test::testExternalRef()
    3127                 :            : {
    3128 [ +  - ][ +  - ]:          3 :     ScDocShellRef xExtDocSh = new ScDocShell;
    3129                 :          3 :     OUString aExtDocName("file:///extdata.fake");
    3130                 :          3 :     OUString aExtSh1Name("Data1");
    3131                 :          3 :     OUString aExtSh2Name("Data2");
    3132                 :          3 :     OUString aExtSh3Name("Data3");
    3133 [ +  - ][ +  - ]:          3 :     SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
         [ +  - ][ +  - ]
    3134         [ +  - ]:          3 :     xExtDocSh->DoInitNew(pMed);
    3135 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3136         [ +  - ]:          3 :                            findLoadedDocShellByName(aExtDocName) != NULL);
    3137                 :            : 
    3138                 :            :     // Populate the external source document.
    3139                 :          3 :     ScDocument* pExtDoc = xExtDocSh->GetDocument();
    3140         [ +  - ]:          3 :     pExtDoc->InsertTab(0, aExtSh1Name);
    3141         [ +  - ]:          3 :     pExtDoc->InsertTab(1, aExtSh2Name);
    3142         [ +  - ]:          3 :     pExtDoc->InsertTab(2, aExtSh3Name);
    3143                 :            : 
    3144                 :          3 :     OUString name("Name");
    3145                 :          3 :     OUString value("Value");
    3146                 :          3 :     OUString andy("Andy");
    3147                 :          3 :     OUString bruce("Bruce");
    3148                 :          3 :     OUString charlie("Charlie");
    3149                 :          3 :     OUString david("David");
    3150                 :          3 :     OUString edward("Edward");
    3151                 :          3 :     OUString frank("Frank");
    3152                 :          3 :     OUString george("George");
    3153                 :          3 :     OUString henry("Henry");
    3154                 :            : 
    3155                 :            :     // Sheet 1
    3156         [ +  - ]:          3 :     pExtDoc->SetString(0, 0, 0, name);
    3157         [ +  - ]:          3 :     pExtDoc->SetString(0, 1, 0, andy);
    3158         [ +  - ]:          3 :     pExtDoc->SetString(0, 2, 0, bruce);
    3159         [ +  - ]:          3 :     pExtDoc->SetString(0, 3, 0, charlie);
    3160         [ +  - ]:          3 :     pExtDoc->SetString(0, 4, 0, david);
    3161         [ +  - ]:          3 :     pExtDoc->SetString(1, 0, 0, value);
    3162                 :          3 :     double val = 10;
    3163         [ +  - ]:          3 :     pExtDoc->SetValue(1, 1, 0, val);
    3164                 :          3 :     val = 11;
    3165         [ +  - ]:          3 :     pExtDoc->SetValue(1, 2, 0, val);
    3166                 :          3 :     val = 12;
    3167         [ +  - ]:          3 :     pExtDoc->SetValue(1, 3, 0, val);
    3168                 :          3 :     val = 13;
    3169         [ +  - ]:          3 :     pExtDoc->SetValue(1, 4, 0, val);
    3170                 :            : 
    3171                 :            :     // Sheet 2 remains empty.
    3172                 :            : 
    3173                 :            :     // Sheet 3
    3174         [ +  - ]:          3 :     pExtDoc->SetString(0, 0, 2, name);
    3175         [ +  - ]:          3 :     pExtDoc->SetString(0, 1, 2, edward);
    3176         [ +  - ]:          3 :     pExtDoc->SetString(0, 2, 2, frank);
    3177         [ +  - ]:          3 :     pExtDoc->SetString(0, 3, 2, george);
    3178         [ +  - ]:          3 :     pExtDoc->SetString(0, 4, 2, henry);
    3179         [ +  - ]:          3 :     pExtDoc->SetString(1, 0, 2, value);
    3180                 :          3 :     val = 99;
    3181         [ +  - ]:          3 :     pExtDoc->SetValue(1, 1, 2, val);
    3182                 :          3 :     val = 98;
    3183         [ +  - ]:          3 :     pExtDoc->SetValue(1, 2, 2, val);
    3184                 :          3 :     val = 97;
    3185         [ +  - ]:          3 :     pExtDoc->SetValue(1, 3, 2, val);
    3186                 :          3 :     val = 96;
    3187         [ +  - ]:          3 :     pExtDoc->SetValue(1, 4, 2, val);
    3188                 :            : 
    3189                 :            :     // Test external refernces on the main document while the external
    3190                 :            :     // document is still in memory.
    3191                 :          3 :     OUString test;
    3192         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Test Sheet"));
    3193         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, OUString("='file:///extdata.fake'#Data1.A1"));
    3194         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 0, test);
    3195 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(name));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3196                 :            : 
    3197                 :            :     // After the initial access to the external document, the external ref
    3198                 :            :     // manager should create sheet cache entries for *all* sheets from that
    3199                 :            :     // document.  Note that the doc may have more than 3 sheets but ensure
    3200                 :            :     // that the first 3 are what we expect.
    3201         [ +  - ]:          3 :     ScExternalRefManager* pRefMgr = m_pDoc->GetExternalRefManager();
    3202         [ +  - ]:          3 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtDocName);
    3203         [ +  - ]:          3 :     vector<OUString> aTabNames;
    3204         [ +  - ]:          3 :     pRefMgr->getAllCachedTableNames(nFileId, aTabNames);
    3205 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be at least 3 sheets.", aTabNames.size() >= 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3206 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[0].equals(aExtSh1Name));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3207 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[1].equals(aExtSh2Name));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3208 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected sheet name.", aTabNames[2].equals(aExtSh3Name));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3209                 :            : 
    3210         [ +  - ]:          3 :     m_pDoc->SetString(1, 0, 0, OUString("='file:///extdata.fake'#Data1.B1"));
    3211         [ +  - ]:          3 :     m_pDoc->GetString(1, 0, 0, test);
    3212 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Value is different from the original", test.equals(value));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3213                 :            : 
    3214         [ +  - ]:          3 :     m_pDoc->SetString(0, 1, 0, OUString("='file:///extdata.fake'#Data1.A2"));
    3215         [ +  - ]:          3 :     m_pDoc->SetString(0, 2, 0, OUString("='file:///extdata.fake'#Data1.A3"));
    3216         [ +  - ]:          3 :     m_pDoc->SetString(0, 3, 0, OUString("='file:///extdata.fake'#Data1.A4"));
    3217         [ +  - ]:          3 :     m_pDoc->SetString(0, 4, 0, OUString("='file:///extdata.fake'#Data1.A5"));
    3218         [ +  - ]:          3 :     m_pDoc->SetString(0, 5, 0, OUString("='file:///extdata.fake'#Data1.A6"));
    3219                 :            : 
    3220                 :            :     {
    3221                 :            :         // Referencing an empty cell should display '0'.
    3222                 :          3 :         const char* pChecks[] = { "Andy", "Bruce", "Charlie", "David", "0" };
    3223         [ +  + ]:         18 :         for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
    3224                 :            :         {
    3225         [ +  - ]:         15 :             m_pDoc->GetString(0, static_cast<SCROW>(i+1), 0, test);
    3226 [ +  - ][ +  - ]:         15 :             CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", test.equalsAscii(pChecks[i]));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3227                 :            :         }
    3228                 :            :     }
    3229         [ +  - ]:          3 :     m_pDoc->SetString(1, 1, 0, OUString("='file:///extdata.fake'#Data1.B2"));
    3230         [ +  - ]:          3 :     m_pDoc->SetString(1, 2, 0, OUString("='file:///extdata.fake'#Data1.B3"));
    3231         [ +  - ]:          3 :     m_pDoc->SetString(1, 3, 0, OUString("='file:///extdata.fake'#Data1.B4"));
    3232         [ +  - ]:          3 :     m_pDoc->SetString(1, 4, 0, OUString("='file:///extdata.fake'#Data1.B5"));
    3233         [ +  - ]:          3 :     m_pDoc->SetString(1, 5, 0, OUString("='file:///extdata.fake'#Data1.B6"));
    3234                 :            :     {
    3235                 :          3 :         double pChecks[] = { 10, 11, 12, 13, 0 };
    3236         [ +  + ]:         18 :         for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
    3237                 :            :         {
    3238         [ +  - ]:         15 :             m_pDoc->GetValue(1, static_cast<SCROW>(i+1), 0, val);
    3239 [ +  - ][ +  - ]:         15 :             CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", val == pChecks[i]);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3240                 :            :         }
    3241                 :            :     }
    3242                 :            : 
    3243         [ +  - ]:          3 :     m_pDoc->SetString(2, 0, 0, OUString("='file:///extdata.fake'#Data3.A1"));
    3244         [ +  - ]:          3 :     m_pDoc->SetString(2, 1, 0, OUString("='file:///extdata.fake'#Data3.A2"));
    3245         [ +  - ]:          3 :     m_pDoc->SetString(2, 2, 0, OUString("='file:///extdata.fake'#Data3.A3"));
    3246         [ +  - ]:          3 :     m_pDoc->SetString(2, 3, 0, OUString("='file:///extdata.fake'#Data3.A4"));
    3247                 :            :     {
    3248                 :          3 :         const char* pChecks[] = { "Name", "Edward", "Frank", "George" };
    3249         [ +  + ]:         15 :         for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
    3250                 :            :         {
    3251         [ +  - ]:         12 :             m_pDoc->GetString(2, static_cast<SCROW>(i), 0, test);
    3252 [ +  - ][ +  - ]:         12 :             CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", test.equalsAscii(pChecks[i]));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3253                 :            :         }
    3254                 :            :     }
    3255                 :            : 
    3256         [ +  - ]:          3 :     m_pDoc->SetString(3, 0, 0, OUString("='file:///extdata.fake'#Data3.B1"));
    3257         [ +  - ]:          3 :     m_pDoc->SetString(3, 1, 0, OUString("='file:///extdata.fake'#Data3.B2"));
    3258         [ +  - ]:          3 :     m_pDoc->SetString(3, 2, 0, OUString("='file:///extdata.fake'#Data3.B3"));
    3259         [ +  - ]:          3 :     m_pDoc->SetString(3, 3, 0, OUString("='file:///extdata.fake'#Data3.B4"));
    3260                 :            :     {
    3261                 :          3 :         const char* pChecks[] = { "Value", "99", "98", "97" };
    3262         [ +  + ]:         15 :         for (size_t i = 0; i < SAL_N_ELEMENTS(pChecks); ++i)
    3263                 :            :         {
    3264         [ +  - ]:         12 :             m_pDoc->GetString(3, static_cast<SCROW>(i), 0, test);
    3265 [ +  - ][ +  - ]:         12 :             CPPUNIT_ASSERT_MESSAGE("Unexpected cell value.", test.equalsAscii(pChecks[i]));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3266                 :            :         }
    3267                 :            :     }
    3268                 :            : 
    3269                 :            :     // At this point, all accessed cell data from the external document should
    3270                 :            :     // have been cached.
    3271                 :            :     ScExternalRefCache::TableTypeRef pCacheTab = pRefMgr->getCacheTable(
    3272         [ +  - ]:          3 :         nFileId, aExtSh1Name, false);
    3273 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 1 should exist.", pCacheTab.get() != NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3274         [ +  - ]:          3 :     ScRange aCachedRange = getCachedRange(pCacheTab);
    3275 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
    3276                 :            :                            aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
    3277         [ +  - ]:          3 :                            aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 4);
    3278                 :            : 
    3279                 :            :     // Sheet2 is not referenced at all; the cache table shouldn't even exist.
    3280 [ +  - ][ +  - ]:          3 :     pCacheTab = pRefMgr->getCacheTable(nFileId, aExtSh2Name, false);
                 [ +  - ]
    3281 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 2 should *not* exist.", pCacheTab.get() == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3282                 :            : 
    3283                 :            :     // Sheet3's row 5 is not referenced; it should not be cached.
    3284 [ +  - ][ +  - ]:          3 :     pCacheTab = pRefMgr->getCacheTable(nFileId, aExtSh3Name, false);
                 [ +  - ]
    3285 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cache table for sheet 3 should exist.", pCacheTab.get() != NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3286         [ +  - ]:          3 :     aCachedRange = getCachedRange(pCacheTab);
    3287 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Unexpected cached data range.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3288                 :            :                            aCachedRange.aStart.Col() == 0 && aCachedRange.aEnd.Col() == 1 &&
    3289         [ +  - ]:          3 :                            aCachedRange.aStart.Row() == 0 && aCachedRange.aEnd.Row() == 3);
    3290                 :            : 
    3291                 :            :     // Unload the external document shell.
    3292         [ +  - ]:          3 :     xExtDocSh->DoClose();
    3293 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3294         [ +  - ]:          3 :                            findLoadedDocShellByName(aExtDocName) == NULL);
    3295                 :            : 
    3296 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
                 [ +  - ]
    3297                 :          3 : }
    3298                 :            : 
    3299                 :          3 : void testExtRefFuncT(ScDocument* pDoc, ScDocument* pExtDoc)
    3300                 :            : {
    3301         [ +  - ]:          3 :     clearRange(pDoc, ScRange(0, 0, 0, 1, 9, 0));
    3302         [ +  - ]:          3 :     clearRange(pExtDoc, ScRange(0, 0, 0, 1, 9, 0));
    3303                 :            : 
    3304         [ +  - ]:          3 :     pExtDoc->SetString(0, 0, 0, rtl::OUString("'1.2"));
    3305         [ +  - ]:          3 :     pExtDoc->SetString(0, 1, 0, rtl::OUString("Foo"));
    3306         [ +  - ]:          3 :     pExtDoc->SetValue(0, 2, 0, 12.3);
    3307         [ +  - ]:          3 :     pDoc->SetString(0, 0, 0, rtl::OUString("=T('file:///extdata.fake'#Data.A1)"));
    3308         [ +  - ]:          3 :     pDoc->SetString(0, 1, 0, rtl::OUString("=T('file:///extdata.fake'#Data.A2)"));
    3309         [ +  - ]:          3 :     pDoc->SetString(0, 2, 0, rtl::OUString("=T('file:///extdata.fake'#Data.A3)"));
    3310         [ +  - ]:          3 :     pDoc->CalcAll();
    3311                 :            : 
    3312         [ +  - ]:          3 :     rtl::OUString aRes = pDoc->GetString(0, 0, 0);
    3313 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "1.2" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3314         [ +  - ]:          3 :     aRes = pDoc->GetString(0, 1, 0);
    3315 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE( "Unexpected result with T.", aRes == "Foo" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3316         [ +  - ]:          3 :     aRes = pDoc->GetString(0, 2, 0);
    3317 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected result with T.", aRes.isEmpty());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3318                 :          3 : }
    3319                 :            : 
    3320                 :          3 : void Test::testExternalRefFunctions()
    3321                 :            : {
    3322 [ +  - ][ +  - ]:          3 :     ScDocShellRef xExtDocSh = new ScDocShell;
    3323                 :          3 :     OUString aExtDocName("file:///extdata.fake");
    3324 [ +  - ][ +  - ]:          3 :     SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
         [ +  - ][ +  - ]
    3325         [ +  - ]:          3 :     xExtDocSh->DoInitNew(pMed);
    3326 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3327         [ +  - ]:          3 :                            findLoadedDocShellByName(aExtDocName) != NULL);
    3328                 :            : 
    3329         [ +  - ]:          3 :     ScExternalRefManager* pRefMgr = m_pDoc->GetExternalRefManager();
    3330 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("external reference manager doesn't exist.", pRefMgr);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3331         [ +  - ]:          3 :     sal_uInt16 nFileId = pRefMgr->getExternalFileId(aExtDocName);
    3332         [ +  - ]:          3 :     const OUString* pFileName = pRefMgr->getExternalFileName(nFileId);
    3333 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("file name registration has somehow failed.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
    3334         [ +  - ]:          3 :                            pFileName && pFileName->equals(aExtDocName));
    3335                 :            : 
    3336                 :            :     // Populate the external source document.
    3337                 :          3 :     ScDocument* pExtDoc = xExtDocSh->GetDocument();
    3338         [ +  - ]:          3 :     pExtDoc->InsertTab(0, rtl::OUString("Data"));
    3339                 :          3 :     double val = 1;
    3340         [ +  - ]:          3 :     pExtDoc->SetValue(0, 0, 0, val);
    3341                 :            :     // leave cell B1 empty.
    3342                 :          3 :     val = 2;
    3343         [ +  - ]:          3 :     pExtDoc->SetValue(0, 1, 0, val);
    3344         [ +  - ]:          3 :     pExtDoc->SetValue(1, 1, 0, val);
    3345                 :          3 :     val = 3;
    3346         [ +  - ]:          3 :     pExtDoc->SetValue(0, 2, 0, val);
    3347         [ +  - ]:          3 :     pExtDoc->SetValue(1, 2, 0, val);
    3348                 :          3 :     val = 4;
    3349         [ +  - ]:          3 :     pExtDoc->SetValue(0, 3, 0, val);
    3350         [ +  - ]:          3 :     pExtDoc->SetValue(1, 3, 0, val);
    3351                 :            : 
    3352         [ +  - ]:          3 :     m_pDoc->InsertTab(0, rtl::OUString("Test"));
    3353                 :            : 
    3354                 :            :     struct {
    3355                 :            :         const char* pFormula; double fResult;
    3356                 :            :     } aChecks[] = {
    3357                 :            :         { "=SUM('file:///extdata.fake'#Data.A1:A4)",     10 },
    3358                 :            :         { "=SUM('file:///extdata.fake'#Data.B1:B4)",     9 },
    3359                 :            :         { "=AVERAGE('file:///extdata.fake'#Data.A1:A4)", 2.5 },
    3360                 :            :         { "=AVERAGE('file:///extdata.fake'#Data.B1:B4)", 3 },
    3361                 :            :         { "=COUNT('file:///extdata.fake'#Data.A1:A4)",   4 },
    3362                 :            :         { "=COUNT('file:///extdata.fake'#Data.B1:B4)",   3 }
    3363                 :          3 :     };
    3364                 :            : 
    3365         [ +  + ]:         21 :     for (size_t i = 0; i < SAL_N_ELEMENTS(aChecks); ++i)
    3366                 :            :     {
    3367         [ +  - ]:         18 :         m_pDoc->SetString(0, 0, 0, rtl::OUString::createFromAscii(aChecks[i].pFormula));
    3368         [ +  - ]:         18 :         m_pDoc->CalcAll();
    3369         [ +  - ]:         18 :         m_pDoc->GetValue(0, 0, 0, val);
    3370 [ +  - ][ +  - ]:         18 :         CPPUNIT_ASSERT_MESSAGE("unexpected result involving external ranges.", val == aChecks[i].fResult);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3371                 :            :     }
    3372                 :            : 
    3373         [ +  - ]:          3 :     pRefMgr->clearCache(nFileId);
    3374         [ +  - ]:          3 :     testExtRefFuncT(m_pDoc, pExtDoc);
    3375                 :            : 
    3376                 :            :     // Unload the external document shell.
    3377         [ +  - ]:          3 :     xExtDocSh->DoClose();
    3378 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("external document instance should have been unloaded.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3379         [ +  - ]:          3 :                            findLoadedDocShellByName(aExtDocName) == NULL);
    3380                 :            : 
    3381 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3382                 :          3 : }
    3383                 :            : 
    3384                 :          3 : void Test::testDataArea()
    3385                 :            : {
    3386         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Data"));
    3387                 :            : 
    3388                 :            :     // Totally empty sheet should be rightfully considered empty in all accounts.
    3389 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Sheet is expected to be empty.", m_pDoc->IsPrintEmpty(0, 0, 0, 100, 100));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3390 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Sheet is expected to be empty.", m_pDoc->IsBlockEmpty(0, 0, 0, 100, 100));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3391                 :            : 
    3392                 :            :     // Now, set borders in some cells....
    3393         [ +  - ]:          3 :     ::editeng::SvxBorderLine aLine(NULL, 50, table::BorderLineStyle::SOLID);
    3394         [ +  - ]:          3 :     SvxBoxItem aBorderItem(ATTR_BORDER);
    3395         [ +  - ]:          3 :     aBorderItem.SetLine(&aLine, BOX_LINE_LEFT);
    3396         [ +  - ]:          3 :     aBorderItem.SetLine(&aLine, BOX_LINE_RIGHT);
    3397         [ +  + ]:        303 :     for (SCROW i = 0; i < 100; ++i)
    3398                 :            :         // Set borders from row 1 to 100.
    3399         [ +  - ]:        300 :         m_pDoc->ApplyAttr(0, i, 0, aBorderItem);
    3400                 :            : 
    3401                 :            :     // Now the sheet is considered non-empty for printing purposes, but still
    3402                 :            :     // be empty in all the other cases.
    3403 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Empty sheet with borders should be printable.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3404         [ +  - ]:          3 :                            !m_pDoc->IsPrintEmpty(0, 0, 0, 100, 100));
    3405 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("But it should still be considered empty in all the other cases.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3406         [ +  - ]:          3 :                            m_pDoc->IsBlockEmpty(0, 0, 0, 100, 100));
    3407                 :            : 
    3408                 :            :     // Adding a real cell content should turn the block non-empty.
    3409         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, OUString("Some text"));
    3410 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Now the block should not be empty with a real cell content.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3411         [ +  - ]:          3 :                            !m_pDoc->IsBlockEmpty(0, 0, 0, 100, 100));
    3412                 :            : 
    3413                 :            :     // TODO: Add more tests for normal data area calculation.
    3414                 :            : 
    3415 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3416                 :          3 : }
    3417                 :            : 
    3418                 :          3 : void Test::testStreamValid()
    3419                 :            : {
    3420         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Sheet1"));
    3421         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Sheet2"));
    3422         [ +  - ]:          3 :     m_pDoc->InsertTab(2, OUString("Sheet3"));
    3423         [ +  - ]:          3 :     m_pDoc->InsertTab(3, OUString("Sheet4"));
    3424 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("We should have 4 sheet instances.", m_pDoc->GetTableCount(), static_cast<SCTAB>(4));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3425                 :            : 
    3426                 :          3 :     OUString a1("A1");
    3427                 :          3 :     OUString a2("A2");
    3428                 :          3 :     OUString test;
    3429                 :            : 
    3430                 :            :     // Put values into Sheet1.
    3431         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 0, a1);
    3432         [ +  - ]:          3 :     m_pDoc->SetString(0, 1, 0, a2);
    3433         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 0, test);
    3434 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet1.A1", test.equals(a1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3435         [ +  - ]:          3 :     m_pDoc->GetString(0, 1, 0, test);
    3436 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet1.A2", test.equals(a2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3437                 :            : 
    3438                 :            :     // Put formulas into Sheet2 to Sheet4 to reference values from Sheet1.
    3439         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 1, OUString("=Sheet1.A1"));
    3440         [ +  - ]:          3 :     m_pDoc->SetString(0, 1, 1, OUString("=Sheet1.A2"));
    3441         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 2, OUString("=Sheet1.A1"));
    3442         [ +  - ]:          3 :     m_pDoc->SetString(0, 0, 3, OUString("=Sheet1.A2"));
    3443                 :            : 
    3444         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 1, test);
    3445 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet2.A1", test.equals(a1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3446         [ +  - ]:          3 :     m_pDoc->GetString(0, 1, 1, test);
    3447 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet2.A2", test.equals(a2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3448         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 2, test);
    3449 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet3.A1", test.equals(a1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3450         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 3, test);
    3451 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Unexpected value in Sheet3.A1", test.equals(a2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3452                 :            : 
    3453                 :            :     // Set all sheet streams valid after all the initial cell values are in
    3454                 :            :     // place. In reality we need to have real XML streams stored in order to
    3455                 :            :     // claim they are valid, but we are just testing the flag values here.
    3456         [ +  - ]:          3 :     m_pDoc->SetStreamValid(0, true);
    3457         [ +  - ]:          3 :     m_pDoc->SetStreamValid(1, true);
    3458         [ +  - ]:          3 :     m_pDoc->SetStreamValid(2, true);
    3459         [ +  - ]:          3 :     m_pDoc->SetStreamValid(3, true);
    3460 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3461 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3462 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3463 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream is expected to be valid.", m_pDoc->IsStreamValid(3));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3464                 :            : 
    3465                 :            :     // Now, insert a new row at row 2 position on Sheet1.  This will move cell
    3466                 :            :     // A2 downward but cell A1 remains unmoved.
    3467         [ +  - ]:          3 :     m_pDoc->InsertRow(0, 0, MAXCOL, 0, 1, 2);
    3468         [ +  - ]:          3 :     m_pDoc->GetString(0, 0, 0, test);
    3469 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cell A1 should not have moved.", test.equals(a1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3470         [ +  - ]:          3 :     m_pDoc->GetString(0, 3, 0, test);
    3471 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the old cell A2 should now be at A4.", test.equals(a2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3472         [ +  - ]:          3 :     const ScBaseCell* pCell = m_pDoc->GetCell(ScAddress(0, 1, 0));
    3473 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cell A2 should be empty.", pCell == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3474         [ +  - ]:          3 :     pCell = m_pDoc->GetCell(ScAddress(0, 2, 0));
    3475 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cell A3 should be empty.", pCell == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3476                 :            : 
    3477                 :            :     // After the move, Sheet1, Sheet2, and Sheet4 should have their stream
    3478                 :            :     // invalidated, whereas Sheet3's stream should still be valid.
    3479 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3480 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3481 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream should have been invalidated.", !m_pDoc->IsStreamValid(3));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3482 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Stream should still be valid.", m_pDoc->IsStreamValid(2));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3483                 :            : 
    3484         [ +  - ]:          3 :     m_pDoc->DeleteTab(3);
    3485         [ +  - ]:          3 :     m_pDoc->DeleteTab(2);
    3486         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    3487         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3488                 :          3 : }
    3489                 :            : 
    3490                 :          3 : void Test::testFunctionLists()
    3491                 :            : {
    3492                 :            :     const char* aDataBase[] = {
    3493                 :            :         "DAVERAGE",
    3494                 :            :         "DCOUNT",
    3495                 :            :         "DCOUNTA",
    3496                 :            :         "DGET",
    3497                 :            :         "DMAX",
    3498                 :            :         "DMIN",
    3499                 :            :         "DPRODUCT",
    3500                 :            :         "DSTDEV",
    3501                 :            :         "DSTDEVP",
    3502                 :            :         "DSUM",
    3503                 :            :         "DVAR",
    3504                 :            :         "DVARP",
    3505                 :            :         0
    3506                 :          3 :     };
    3507                 :            : 
    3508                 :            :     const char* aDateTime[] = {
    3509                 :            :         "DATE",
    3510                 :            :         "DATEDIF",
    3511                 :            :         "DATEVALUE",
    3512                 :            :         "DAY",
    3513                 :            :         "DAYS",
    3514                 :            :         "DAYS360",
    3515                 :            :         "EASTERSUNDAY",
    3516                 :            :         "HOUR",
    3517                 :            :         "MINUTE",
    3518                 :            :         "MONTH",
    3519                 :            :         "NOW",
    3520                 :            :         "SECOND",
    3521                 :            :         "TIME",
    3522                 :            :         "TIMEVALUE",
    3523                 :            :         "TODAY",
    3524                 :            :         "WEEKDAY",
    3525                 :            :         "WEEKNUM",
    3526                 :            :         "YEAR",
    3527                 :            :         0
    3528                 :          3 :     };
    3529                 :            : 
    3530                 :            :     const char* aFinancial[] = {
    3531                 :            :         "CUMIPMT",
    3532                 :            :         "CUMPRINC",
    3533                 :            :         "DB",
    3534                 :            :         "DDB",
    3535                 :            :         "DURATION",
    3536                 :            :         "EFFECTIVE",
    3537                 :            :         "FV",
    3538                 :            :         "IPMT",
    3539                 :            :         "IRR",
    3540                 :            :         "ISPMT",
    3541                 :            :         "MIRR",
    3542                 :            :         "NOMINAL",
    3543                 :            :         "NPER",
    3544                 :            :         "NPV",
    3545                 :            :         "PMT",
    3546                 :            :         "PPMT",
    3547                 :            :         "PV",
    3548                 :            :         "RATE",
    3549                 :            :         "RRI",
    3550                 :            :         "SLN",
    3551                 :            :         "SYD",
    3552                 :            :         "VDB",
    3553                 :            :         0
    3554                 :          3 :     };
    3555                 :            : 
    3556                 :            :     const char* aInformation[] = {
    3557                 :            :         "CELL",
    3558                 :            :         "CURRENT",
    3559                 :            :         "FORMULA",
    3560                 :            :         "INFO",
    3561                 :            :         "ISBLANK",
    3562                 :            :         "ISERR",
    3563                 :            :         "ISERROR",
    3564                 :            :         "ISFORMULA",
    3565                 :            :         "ISLOGICAL",
    3566                 :            :         "ISNA",
    3567                 :            :         "ISNONTEXT",
    3568                 :            :         "ISNUMBER",
    3569                 :            :         "ISREF",
    3570                 :            :         "ISTEXT",
    3571                 :            :         "N",
    3572                 :            :         "NA",
    3573                 :            :         "TYPE",
    3574                 :            :         0
    3575                 :          3 :     };
    3576                 :            : 
    3577                 :            :     const char* aLogical[] = {
    3578                 :            :         "AND",
    3579                 :            :         "FALSE",
    3580                 :            :         "IF",
    3581                 :            :         "NOT",
    3582                 :            :         "OR",
    3583                 :            :         "TRUE",
    3584                 :            :         "XOR",
    3585                 :            :         0
    3586                 :          3 :     };
    3587                 :            : 
    3588                 :            :     const char* aMathematical[] = {
    3589                 :            :         "ABS",
    3590                 :            :         "ACOS",
    3591                 :            :         "ACOSH",
    3592                 :            :         "ACOT",
    3593                 :            :         "ACOTH",
    3594                 :            :         "ASIN",
    3595                 :            :         "ASINH",
    3596                 :            :         "ATAN",
    3597                 :            :         "ATAN2",
    3598                 :            :         "ATANH",
    3599                 :            :         "BITAND",
    3600                 :            :         "BITLSHIFT",
    3601                 :            :         "BITOR",
    3602                 :            :         "BITRSHIFT",
    3603                 :            :         "BITXOR",
    3604                 :            :         "CEILING",
    3605                 :            :         "COMBIN",
    3606                 :            :         "COMBINA",
    3607                 :            :         "CONVERT",
    3608                 :            :         "COS",
    3609                 :            :         "COSH",
    3610                 :            :         "COT",
    3611                 :            :         "COTH",
    3612                 :            :         "COUNTBLANK",
    3613                 :            :         "COUNTIF",
    3614                 :            :         "CSC",
    3615                 :            :         "CSCH",
    3616                 :            :         "DEGREES",
    3617                 :            :         "EUROCONVERT",
    3618                 :            :         "EVEN",
    3619                 :            :         "EXP",
    3620                 :            :         "FACT",
    3621                 :            :         "FLOOR",
    3622                 :            :         "GCD",
    3623                 :            :         "INT",
    3624                 :            :         "ISEVEN",
    3625                 :            :         "ISODD",
    3626                 :            :         "LCM",
    3627                 :            :         "LN",
    3628                 :            :         "LOG",
    3629                 :            :         "LOG10",
    3630                 :            :         "MOD",
    3631                 :            :         "ODD",
    3632                 :            :         "PI",
    3633                 :            :         "POWER",
    3634                 :            :         "PRODUCT",
    3635                 :            :         "RADIANS",
    3636                 :            :         "RAND",
    3637                 :            :         "ROUND",
    3638                 :            :         "ROUNDDOWN",
    3639                 :            :         "ROUNDUP",
    3640                 :            :         "SEC",
    3641                 :            :         "SECH",
    3642                 :            :         "SIGN",
    3643                 :            :         "SIN",
    3644                 :            :         "SINH",
    3645                 :            :         "SQRT",
    3646                 :            :         "SUBTOTAL",
    3647                 :            :         "SUM",
    3648                 :            :         "SUMIF",
    3649                 :            :         "SUMSQ",
    3650                 :            :         "TAN",
    3651                 :            :         "TANH",
    3652                 :            :         "TRUNC",
    3653                 :            :         0
    3654                 :          3 :     };
    3655                 :            : 
    3656                 :            :     const char* aArray[] = {
    3657                 :            :         "FREQUENCY",
    3658                 :            :         "GROWTH",
    3659                 :            :         "LINEST",
    3660                 :            :         "LOGEST",
    3661                 :            :         "MDETERM",
    3662                 :            :         "MINVERSE",
    3663                 :            :         "MMULT",
    3664                 :            :         "MUNIT",
    3665                 :            :         "SUMPRODUCT",
    3666                 :            :         "SUMX2MY2",
    3667                 :            :         "SUMX2PY2",
    3668                 :            :         "SUMXMY2",
    3669                 :            :         "TRANSPOSE",
    3670                 :            :         "TREND",
    3671                 :            :         0
    3672                 :          3 :     };
    3673                 :            : 
    3674                 :            :     const char* aStatistical[] = {
    3675                 :            :         "AVEDEV",
    3676                 :            :         "AVERAGE",
    3677                 :            :         "AVERAGEA",
    3678                 :            :         "B",
    3679                 :            :         "BETADIST",
    3680                 :            :         "BETAINV",
    3681                 :            :         "BINOMDIST",
    3682                 :            :         "CHIDIST",
    3683                 :            :         "CHIINV",
    3684                 :            :         "CHISQDIST",
    3685                 :            :         "CHISQINV",
    3686                 :            :         "CHITEST",
    3687                 :            :         "CONFIDENCE",
    3688                 :            :         "CORREL",
    3689                 :            :         "COUNT",
    3690                 :            :         "COUNTA",
    3691                 :            :         "COVAR",
    3692                 :            :         "CRITBINOM",
    3693                 :            :         "DEVSQ",
    3694                 :            :         "EXPONDIST",
    3695                 :            :         "FDIST",
    3696                 :            :         "FINV",
    3697                 :            :         "FISHER",
    3698                 :            :         "FISHERINV",
    3699                 :            :         "FORECAST",
    3700                 :            :         "FTEST",
    3701                 :            :         "GAMMA",
    3702                 :            :         "GAMMADIST",
    3703                 :            :         "GAMMAINV",
    3704                 :            :         "GAMMALN",
    3705                 :            :         "GAUSS",
    3706                 :            :         "GEOMEAN",
    3707                 :            :         "HARMEAN",
    3708                 :            :         "HYPGEOMDIST",
    3709                 :            :         "INTERCEPT",
    3710                 :            :         "KURT",
    3711                 :            :         "LARGE",
    3712                 :            :         "LOGINV",
    3713                 :            :         "LOGNORMDIST",
    3714                 :            :         "MAX",
    3715                 :            :         "MAXA",
    3716                 :            :         "MEDIAN",
    3717                 :            :         "MIN",
    3718                 :            :         "MINA",
    3719                 :            :         "MODE",
    3720                 :            :         "NEGBINOMDIST",
    3721                 :            :         "NORMDIST",
    3722                 :            :         "NORMINV",
    3723                 :            :         "NORMSDIST",
    3724                 :            :         "NORMSINV",
    3725                 :            :         "PEARSON",
    3726                 :            :         "PERCENTILE",
    3727                 :            :         "PERCENTRANK",
    3728                 :            :         "PERMUT",
    3729                 :            :         "PERMUTATIONA",
    3730                 :            :         "PHI",
    3731                 :            :         "POISSON",
    3732                 :            :         "PROB",
    3733                 :            :         "QUARTILE",
    3734                 :            :         "RANK",
    3735                 :            :         "RSQ",
    3736                 :            :         "SKEW",
    3737                 :            :         "SLOPE",
    3738                 :            :         "SMALL",
    3739                 :            :         "STANDARDIZE",
    3740                 :            :         "STDEV",
    3741                 :            :         "STDEVA",
    3742                 :            :         "STDEVP",
    3743                 :            :         "STDEVPA",
    3744                 :            :         "STEYX",
    3745                 :            :         "TDIST",
    3746                 :            :         "TINV",
    3747                 :            :         "TRIMMEAN",
    3748                 :            :         "TTEST",
    3749                 :            :         "VAR",
    3750                 :            :         "VARA",
    3751                 :            :         "VARP",
    3752                 :            :         "VARPA",
    3753                 :            :         "WEIBULL",
    3754                 :            :         "ZTEST",
    3755                 :            :         0
    3756                 :          3 :     };
    3757                 :            : 
    3758                 :            :     const char* aSpreadsheet[] = {
    3759                 :            :         "ADDRESS",
    3760                 :            :         "AREAS",
    3761                 :            :         "CHOOSE",
    3762                 :            :         "COLUMN",
    3763                 :            :         "COLUMNS",
    3764                 :            :         "DDE",
    3765                 :            :         "ERRORTYPE",
    3766                 :            :         "GETPIVOTDATA",
    3767                 :            :         "HLOOKUP",
    3768                 :            :         "HYPERLINK",
    3769                 :            :         "INDEX",
    3770                 :            :         "INDIRECT",
    3771                 :            :         "LOOKUP",
    3772                 :            :         "MATCH",
    3773                 :            :         "OFFSET",
    3774                 :            :         "ROW",
    3775                 :            :         "ROWS",
    3776                 :            :         "SHEET",
    3777                 :            :         "SHEETS",
    3778                 :            :         "STYLE",
    3779                 :            :         "VLOOKUP",
    3780                 :            :         0
    3781                 :          3 :     };
    3782                 :            : 
    3783                 :            :     const char* aText[] = {
    3784                 :            :         "ARABIC",
    3785                 :            :         "ASC",
    3786                 :            :         "BAHTTEXT",
    3787                 :            :         "BASE",
    3788                 :            :         "CHAR",
    3789                 :            :         "CLEAN",
    3790                 :            :         "CODE",
    3791                 :            :         "CONCATENATE",
    3792                 :            :         "DECIMAL",
    3793                 :            :         "DOLLAR",
    3794                 :            :         "EXACT",
    3795                 :            :         "FIND",
    3796                 :            :         "FIXED",
    3797                 :            :         "JIS",
    3798                 :            :         "LEFT",
    3799                 :            :         "LEN",
    3800                 :            :         "LOWER",
    3801                 :            :         "MID",
    3802                 :            :         "PROPER",
    3803                 :            :         "REPLACE",
    3804                 :            :         "REPT",
    3805                 :            :         "RIGHT",
    3806                 :            :         "ROMAN",
    3807                 :            :         "SEARCH",
    3808                 :            :         "SUBSTITUTE",
    3809                 :            :         "T",
    3810                 :            :         "TEXT",
    3811                 :            :         "TRIM",
    3812                 :            :         "UNICHAR",
    3813                 :            :         "UNICODE",
    3814                 :            :         "UPPER",
    3815                 :            :         "VALUE",
    3816                 :            :         0
    3817                 :          3 :     };
    3818                 :            : 
    3819                 :            :     struct {
    3820                 :            :         const char* Category; const char** Functions;
    3821                 :            :     } aTests[] = {
    3822                 :            :         { "Database",     aDataBase },
    3823                 :            :         { "Date&Time",    aDateTime },
    3824                 :            :         { "Financial",    aFinancial },
    3825                 :            :         { "Information",  aInformation },
    3826                 :            :         { "Logical",      aLogical },
    3827                 :            :         { "Mathematical", aMathematical },
    3828                 :            :         { "Array",        aArray },
    3829                 :            :         { "Statistical",  aStatistical },
    3830                 :            :         { "Spreadsheet",  aSpreadsheet },
    3831                 :            :         { "Text",         aText },
    3832                 :            :         { "Add-in",       0 },
    3833                 :            :         { 0, 0 }
    3834                 :          3 :     };
    3835                 :            : 
    3836         [ +  - ]:          3 :     ScFunctionMgr* pFuncMgr = ScGlobal::GetStarCalcFunctionMgr();
    3837         [ +  - ]:          3 :     sal_uInt32 n = pFuncMgr->getCount();
    3838         [ +  + ]:         36 :     for (sal_uInt32 i = 0; i < n; ++i)
    3839                 :            :     {
    3840         [ +  - ]:         33 :         const formula::IFunctionCategory* pCat = pFuncMgr->getCategory(i);
    3841 [ +  - ][ +  - ]:         33 :         CPPUNIT_ASSERT_MESSAGE("Unexpected category name", pCat->getName().equalsAscii(aTests[i].Category));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3842         [ +  - ]:         33 :         sal_uInt32 nFuncCount = pCat->getCount();
    3843         [ +  + ]:        894 :         for (sal_uInt32 j = 0; j < nFuncCount; ++j)
    3844                 :            :         {
    3845         [ +  - ]:        861 :             const formula::IFunctionDescription* pFunc = pCat->getFunction(j);
    3846 [ +  - ][ +  - ]:        861 :             CPPUNIT_ASSERT_MESSAGE("Unexpected function name", pFunc->getFunctionName().equalsAscii(aTests[i].Functions[j]));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3847                 :            :         }
    3848                 :            :     }
    3849                 :          3 : }
    3850                 :            : 
    3851                 :          3 : void Test::testGraphicsInGroup()
    3852                 :            : {
    3853                 :          3 :     OUString aTabName("TestTab");
    3854         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aTabName);
    3855 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("document should have one sheet to begin with.", m_pDoc->GetTableCount() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3856                 :            :     SCROW nRow1, nRow2;
    3857         [ +  - ]:          3 :     bool bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    3858 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("new sheet should have all rows visible", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3859                 :            : 
    3860         [ +  - ]:          3 :     m_pDoc->InitDrawLayer();
    3861         [ +  - ]:          3 :     ScDrawLayer *pDrawLayer = m_pDoc->GetDrawLayer();
    3862 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("must have a draw layer", pDrawLayer != NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3863         [ +  - ]:          3 :     SdrPage* pPage = pDrawLayer->GetPage(0);
    3864 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("must have a draw page", pPage != NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3865                 :            : 
    3866                 :            :     {
    3867                 :            :         //Add a square
    3868         [ +  - ]:          3 :         Rectangle aOrigRect(2,2,100,100);
    3869 [ +  - ][ +  - ]:          3 :         SdrRectObj *pObj = new SdrRectObj(aOrigRect);
    3870         [ +  - ]:          3 :         pPage->InsertObject(pObj);
    3871         [ +  - ]:          3 :         const Rectangle &rNewRect = pObj->GetLogicRect();
    3872 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("must have equal position and size", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3873                 :            : 
    3874         [ +  - ]:          3 :         ScDrawLayer::SetPageAnchored(*pObj);
    3875                 :            : 
    3876                 :            :         //Use a range of rows guaranteed to include all of the square
    3877         [ +  - ]:          3 :         m_pDoc->ShowRows(0, 100, 0, false);
    3878 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3879         [ +  - ]:          3 :         m_pDoc->ShowRows(0, 100, 0, true);
    3880 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3881                 :            : 
    3882         [ +  - ]:          3 :         ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
    3883 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("That shouldn't change size or positioning", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3884                 :            : 
    3885         [ +  - ]:          3 :         m_pDoc->ShowRows(0, 100, 0, false);
    3886 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Left and Right should be unchanged",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
    3887         [ +  - ]:          3 :             aOrigRect.nLeft == rNewRect.nLeft && aOrigRect.nRight == rNewRect.nRight);
    3888 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Height should be minimum allowed height",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3889         [ +  - ]:          3 :             (rNewRect.nBottom - rNewRect.nTop) <= 1);
    3890         [ +  - ]:          3 :         m_pDoc->ShowRows(0, 100, 0, true);
    3891 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Should not change when page anchored", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3892                 :            :     }
    3893                 :            : 
    3894                 :            :     {
    3895                 :            :         // Add a circle.
    3896         [ +  - ]:          3 :         Rectangle aOrigRect = Rectangle(10,10,210,210); // 200 x 200
    3897 [ +  - ][ +  - ]:          3 :         SdrCircObj* pObj = new SdrCircObj(OBJ_CIRC, aOrigRect);
    3898         [ +  - ]:          3 :         pPage->InsertObject(pObj);
    3899         [ +  - ]:          3 :         const Rectangle& rNewRect = pObj->GetLogicRect();
    3900 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Position and size of the circle shouldn't change when inserted into the page.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3901         [ +  - ]:          3 :                                aOrigRect == rNewRect);
    3902                 :            : 
    3903         [ +  - ]:          3 :         ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
    3904 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Size changed when cell anchored. Not good.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3905         [ +  - ]:          3 :                                aOrigRect == rNewRect);
    3906                 :            : 
    3907                 :            :         // Insert 2 rows at the top.  This should push the circle object down.
    3908         [ +  - ]:          3 :         m_pDoc->InsertRow(0, 0, MAXCOL, 0, 0, 2);
    3909                 :            : 
    3910                 :            :         // Make sure the size of the circle is still identical.
    3911 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Size of the circle has changed, but shouldn't!",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3912         [ +  - ]:          3 :                                aOrigRect.GetSize() == rNewRect.GetSize());
    3913                 :            : 
    3914                 :            :         // Delete 2 rows at the top.  This should bring the circle object to its original position.
    3915         [ +  - ]:          3 :         m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 0, 2);
    3916 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Failed to move back to its original position.", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3917                 :            :     }
    3918                 :            : 
    3919                 :            :     {
    3920                 :            :         // Add a line.
    3921         [ +  - ]:          3 :         basegfx::B2DPolygon aTempPoly;
    3922                 :          3 :         Point aStartPos(10,300), aEndPos(110,200); // bottom-left to top-right.
    3923         [ +  - ]:          3 :         Rectangle aOrigRect(10,200,110,300); // 100 x 100
    3924         [ +  - ]:          3 :         aTempPoly.append(basegfx::B2DPoint(aStartPos.X(), aStartPos.Y()));
    3925         [ +  - ]:          3 :         aTempPoly.append(basegfx::B2DPoint(aEndPos.X(), aEndPos.Y()));
    3926 [ +  - ][ +  - ]:          3 :         SdrPathObj* pObj = new SdrPathObj(OBJ_LINE, basegfx::B2DPolyPolygon(aTempPoly));
         [ +  - ][ +  - ]
    3927         [ +  - ]:          3 :         pObj->NbcSetLogicRect(aOrigRect);
    3928         [ +  - ]:          3 :         pPage->InsertObject(pObj);
    3929         [ +  - ]:          3 :         const Rectangle& rNewRect = pObj->GetLogicRect();
    3930 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Size differ.", aOrigRect == rNewRect);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3931                 :            : 
    3932         [ +  - ]:          3 :         ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
    3933 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Size changed when cell-anchored. Not good.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3934         [ +  - ]:          3 :                                aOrigRect == rNewRect);
    3935                 :            : 
    3936                 :            :         // Insert 2 rows at the top and delete them immediately.
    3937         [ +  - ]:          3 :         m_pDoc->InsertRow(0, 0, MAXCOL, 0, 0, 2);
    3938         [ +  - ]:          3 :         m_pDoc->DeleteRow(0, 0, MAXCOL, 0, 0, 2);
    3939 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Size of a line object changed after row insertion and removal.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3940         [ +  - ]:          3 :                                aOrigRect == rNewRect);
    3941                 :            : 
    3942         [ +  - ]:          3 :         sal_Int32 n = pObj->GetPointCount();
    3943 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("There should be exactly 2 points in a line object.", n == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3944 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("Line shape has changed.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
           [ #  #  #  # ]
                 [ +  - ]
    3945   [ +  -  +  - ]:          6 :                                aStartPos == pObj->GetPoint(0) && aEndPos == pObj->GetPoint(1));
    3946                 :            :     }
    3947                 :            : 
    3948         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3949                 :          3 : }
    3950                 :            : 
    3951                 :          3 : void Test::testGraphicsOnSheetMove()
    3952                 :            : {
    3953         [ +  - ]:          3 :     m_pDoc->InsertTab(0, rtl::OUString("Tab1"));
    3954         [ +  - ]:          3 :     m_pDoc->InsertTab(1, rtl::OUString("Tab2"));
    3955 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("There should be only 2 sheets to begin with", m_pDoc->GetTableCount() == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3956                 :            : 
    3957         [ +  - ]:          3 :     m_pDoc->InitDrawLayer();
    3958         [ +  - ]:          3 :     ScDrawLayer* pDrawLayer = m_pDoc->GetDrawLayer();
    3959 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No drawing layer.", pDrawLayer);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3960         [ +  - ]:          3 :     SdrPage* pPage = pDrawLayer->GetPage(0);
    3961 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No page instance for the 1st sheet.", pPage);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3962                 :            : 
    3963                 :            :     // Insert an object.
    3964         [ +  - ]:          3 :     Rectangle aObjRect(2,2,100,100);
    3965 [ +  - ][ +  - ]:          3 :     SdrObject* pObj = new SdrRectObj(aObjRect);
    3966         [ +  - ]:          3 :     pPage->InsertObject(pObj);
    3967         [ +  - ]:          3 :     ScDrawLayer::SetCellAnchoredFromPosition(*pObj, *m_pDoc, 0);
    3968                 :            : 
    3969 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be one object on the 1st sheet.", pPage->GetObjCount(), static_cast<sal_uIntPtr>(1));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3970                 :            : 
    3971         [ +  - ]:          3 :     const ScDrawObjData* pData = ScDrawLayer::GetObjData(pObj);
    3972 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Object meta-data doesn't exist.", pData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3973 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 0 && pData->maEnd.Tab() == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3974                 :            : 
    3975         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(1);
    3976 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("No page instance for the 2nd sheet.", pPage);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3977 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("2nd sheet shouldn't have any object.", pPage->GetObjCount(), static_cast<sal_uIntPtr>(0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3978                 :            : 
    3979                 :            :     // Insert a new sheet at left-end, and make sure the object has moved to
    3980                 :            :     // the 2nd page.
    3981         [ +  - ]:          3 :     m_pDoc->InsertTab(0, rtl::OUString("NewTab"));
    3982 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL_MESSAGE("There should be 3 sheets.", m_pDoc->GetTableCount(), static_cast<SCTAB>(3));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3983         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(0);
    3984 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("1st sheet should have no object.", pPage && pPage->GetObjCount() == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3985         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(1);
    3986 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("2nd sheet should have one object.", pPage && pPage->GetObjCount() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3987         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(2);
    3988 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("3rd sheet should have no object.", pPage && pPage->GetObjCount() == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3989                 :            : 
    3990 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 1 && pData->maEnd.Tab() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    3991                 :            : 
    3992                 :            :     // Now, delete the sheet that just got inserted. The object should be back
    3993                 :            :     // on the 1st sheet.
    3994         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    3995         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(0);
    3996 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("1st sheet should have one object.", pPage && pPage->GetObjCount() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    3997 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("Size and position of the object shouldn't change.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    3998         [ +  - ]:          3 :                            pObj->GetLogicRect() == aObjRect);
    3999                 :            : 
    4000 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 0 && pData->maEnd.Tab() == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4001                 :            : 
    4002                 :            :     // Move the 1st sheet to the last position.
    4003         [ +  - ]:          3 :     m_pDoc->MoveTab(0, 1);
    4004         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(0);
    4005 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("1st sheet should have no object.", pPage && pPage->GetObjCount() == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4006         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(1);
    4007 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("2nd sheet should have one object.", pPage && pPage->GetObjCount() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4008 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 1 && pData->maEnd.Tab() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4009                 :            : 
    4010                 :            :     // Copy the 2nd sheet, which has one drawing object to the last position.
    4011         [ +  - ]:          3 :     m_pDoc->CopyTab(1, 2);
    4012         [ +  - ]:          3 :     pPage = pDrawLayer->GetPage(2);
    4013 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Copied sheet should have one object.", pPage && pPage->GetObjCount() == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4014         [ +  - ]:          3 :     pObj = pPage->GetObj(0);
    4015 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object.", pObj);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4016         [ +  - ]:          3 :     pData = ScDrawLayer::GetObjData(pObj);
    4017 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Failed to get drawing object meta-data.", pData);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4018 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Wrong sheet ID in cell anchor data!", pData->maStart.Tab() == 2 && pData->maEnd.Tab() == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4019                 :            : 
    4020         [ +  - ]:          3 :     m_pDoc->DeleteTab(2);
    4021         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    4022         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4023                 :          3 : }
    4024                 :            : 
    4025                 :          3 : void Test::testPostIts()
    4026                 :            : {
    4027                 :          3 :     rtl::OUString aHello("Hello world");
    4028                 :          3 :     rtl::OUString aJimBob("Jim Bob");
    4029                 :          3 :     rtl::OUString aTabName("PostIts");
    4030                 :          3 :     rtl::OUString aTabName2("Table2");
    4031         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aTabName);
    4032                 :            : 
    4033                 :          3 :     ScAddress rAddr(2, 2, 0);
    4034 [ +  - ][ +  - ]:          3 :     ScPostIt *pNote = m_pDoc->GetNotes(rAddr.Tab())->GetOrCreateNote(rAddr);
    4035         [ +  - ]:          3 :     pNote->SetText(rAddr, aHello);
    4036                 :          3 :     pNote->SetAuthor(aJimBob);
    4037                 :            : 
    4038 [ +  - ][ +  - ]:          3 :     ScPostIt *pGetNote = m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr);
    4039 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note should be itself", pGetNote == pNote );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4040                 :            : 
    4041         [ +  - ]:          3 :     bool bInsertRow = m_pDoc->InsertRow( 0, 0, 100, 0, 1, 1 );
    4042 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert row", bInsertRow );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4043                 :            : 
    4044 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4045         [ +  - ]:          3 :     rAddr.IncRow();
    4046 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4047                 :            : 
    4048         [ +  - ]:          3 :     bool bInsertCol = m_pDoc->InsertCol( 0, 0, 100, 0, 1, 1 );
    4049 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert column", bInsertCol );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4050                 :            : 
    4051 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4052         [ +  - ]:          3 :     rAddr.IncCol();
    4053 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4054                 :            : 
    4055         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aTabName2);
    4056 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note hasn't moved", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4057         [ +  - ]:          3 :     rAddr.IncTab();
    4058 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4059                 :            : 
    4060         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4061         [ +  - ]:          3 :     rAddr.IncTab(-1);
    4062 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("note not there", m_pDoc->GetNotes(rAddr.Tab())->findByAddress(rAddr) == pNote);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4063                 :            : 
    4064         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4065                 :          3 : }
    4066                 :            : 
    4067                 :          3 : void Test::testToggleRefFlag()
    4068                 :            : {
    4069                 :            :     // In this test, there is no need to insert formula string into a cell in
    4070                 :            :     // the document, as ScRefFinder does not depend on the content of the
    4071                 :            :     // document except for the sheet names.
    4072                 :            : 
    4073                 :          3 :     OUString aTabName("Test");
    4074         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aTabName);
    4075                 :            : 
    4076                 :            :     {
    4077                 :            :         // Calc A1: basic 2D reference
    4078                 :            : 
    4079                 :          3 :         OUString aFormula("=B100");
    4080                 :          3 :         ScAddress aPos(1, 5, 0);
    4081 [ +  - ][ +  - ]:          3 :         ScRefFinder aFinder(aFormula, aPos, m_pDoc, formula::FormulaGrammar::CONV_OOO);
                 [ +  - ]
    4082                 :            : 
    4083                 :            :         // Original
    4084 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula.equals(aFinder.GetText()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4085                 :            : 
    4086                 :            :         // column relative / row relative -> column absolute / row absolute
    4087         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4088         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4089 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=$B$100" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4090                 :            : 
    4091                 :            :         // column absolute / row absolute -> column relative / row absolute
    4092         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4093         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4094 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=B$100" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4095                 :            : 
    4096                 :            :         // column relative / row absolute -> column absolute / row relative
    4097         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4098         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4099 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=$B100" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4100                 :            : 
    4101                 :            :         // column absolute / row relative -> column relative / row relative
    4102         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4103         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4104 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=B100" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4105                 :            :     }
    4106                 :            : 
    4107                 :            :     {
    4108                 :            :         // Excel R1C1: basic 2D reference
    4109                 :            : 
    4110                 :          3 :         OUString aFormula("=R2C1");
    4111                 :          3 :         ScAddress aPos(3, 5, 0);
    4112 [ +  - ][ +  - ]:          3 :         ScRefFinder aFinder(aFormula, aPos, m_pDoc, formula::FormulaGrammar::CONV_XL_R1C1);
                 [ +  - ]
    4113                 :            : 
    4114                 :            :         // Original
    4115 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE("Does not equal the original text.", aFormula.equals(aFinder.GetText()));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4116                 :            : 
    4117                 :            :         // column absolute / row absolute -> column relative / row absolute
    4118         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4119         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4120 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R2C[-3]" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4121                 :            : 
    4122                 :            :         // column relative / row absolute - > column absolute / row relative
    4123         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4124         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4125 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R[-4]C1" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4126                 :            : 
    4127                 :            :         // column absolute / row relative -> column relative / row relative
    4128         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4129         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4130 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R[-4]C[-3]" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4131                 :            : 
    4132                 :            :         // column relative / row relative -> column absolute / row absolute
    4133         [ +  - ]:          3 :         aFinder.ToggleRel(0, aFormula.getLength());
    4134         [ +  - ]:          3 :         aFormula = aFinder.GetText();
    4135 [ +  - ][ +  - ]:          3 :         CPPUNIT_ASSERT_MESSAGE( "Wrong conversion.", aFormula == "=R2C1" );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4136                 :            :     }
    4137                 :            : 
    4138                 :            :     // TODO: Add more test cases esp. for 3D references, Excel A1 syntax, and
    4139                 :            :     // partial selection within formula string.
    4140                 :            : 
    4141         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4142                 :          3 : }
    4143                 :            : 
    4144                 :          3 : void Test::testAutofilter()
    4145                 :            : {
    4146                 :          3 :     OUString aTabName("Test");
    4147                 :          3 :     OUString aDBName("NONAME");
    4148                 :            : 
    4149         [ +  - ]:          3 :     m_pDoc->InsertTab( 0, aTabName );
    4150                 :            : 
    4151                 :            :     // cell contents (0 = empty cell)
    4152                 :            :     const char* aData[][3] = {
    4153                 :            :         { "C1", "C2", "C3" },
    4154                 :            :         {  "0",  "1",  "A" },
    4155                 :            :         {  "1",  "2",    0 },
    4156                 :            :         {  "1",  "2",  "B" },
    4157                 :            :         {  "0",  "2",  "B" }
    4158                 :          3 :     };
    4159                 :            : 
    4160                 :          3 :     SCCOL nCols = SAL_N_ELEMENTS(aData[0]);
    4161                 :          3 :     SCROW nRows = SAL_N_ELEMENTS(aData);
    4162                 :            : 
    4163                 :            :     // Populate cells.
    4164         [ +  + ]:         18 :     for (SCROW i = 0; i < nRows; ++i)
    4165         [ +  + ]:         60 :         for (SCCOL j = 0; j < nCols; ++j)
    4166         [ +  + ]:         45 :             if (aData[i][j])
    4167         [ +  - ]:         42 :                 m_pDoc->SetString(j, i, 0, rtl::OUString::createFromAscii(aData[i][j]));
    4168                 :            : 
    4169 [ +  - ][ +  - ]:          3 :     ScDBData* pDBData = new ScDBData(aDBName, 0, 0, 0, nCols-1, nRows-1);
    4170         [ +  - ]:          3 :     m_pDoc->SetAnonymousDBData(0,pDBData);
    4171                 :            : 
    4172                 :          3 :     pDBData->SetAutoFilter(true);
    4173                 :          3 :     ScRange aRange;
    4174         [ +  - ]:          3 :     pDBData->GetArea(aRange);
    4175                 :          3 :     m_pDoc->ApplyFlagsTab( aRange.aStart.Col(), aRange.aStart.Row(),
    4176                 :          3 :                            aRange.aEnd.Col(), aRange.aStart.Row(),
    4177         [ +  - ]:          9 :                            aRange.aStart.Tab(), SC_MF_AUTO);
    4178                 :            : 
    4179                 :            :     //create the query param
    4180         [ +  - ]:          3 :     ScQueryParam aParam;
    4181         [ +  - ]:          3 :     pDBData->GetQueryParam(aParam);
    4182         [ +  - ]:          3 :     ScQueryEntry& rEntry = aParam.GetEntry(0);
    4183                 :          3 :     rEntry.bDoQuery = true;
    4184                 :          3 :     rEntry.nField = 0;
    4185                 :          3 :     rEntry.eOp = SC_EQUAL;
    4186         [ +  - ]:          3 :     rEntry.GetQueryItem().mfVal = 0;
    4187                 :            :     // add queryParam to database range.
    4188         [ +  - ]:          3 :     pDBData->SetQueryParam(aParam);
    4189                 :            : 
    4190                 :            :     // perform the query.
    4191         [ +  - ]:          3 :     m_pDoc->Query(0, aParam, true);
    4192                 :            : 
    4193                 :            :     //control output
    4194                 :            :     SCROW nRow1, nRow2;
    4195         [ +  - ]:          3 :     bool bHidden = m_pDoc->RowHidden(2, 0, &nRow1, &nRow2);
    4196 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 2 & 3 should be hidden", bHidden && nRow1 == 2 && nRow2 == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4197                 :            : 
    4198                 :            :     // Remove filtering.
    4199         [ +  - ]:          3 :     rEntry.Clear();
    4200         [ +  - ]:          3 :     m_pDoc->Query(0, aParam, true);
    4201         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    4202 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("All rows should be shown.", !bHidden && nRow1 == 0 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4203                 :            : 
    4204                 :            :     // Filter for non-empty cells by column C.
    4205                 :          3 :     rEntry.bDoQuery = true;
    4206                 :          3 :     rEntry.nField = 2;
    4207         [ +  - ]:          3 :     rEntry.SetQueryByNonEmpty();
    4208         [ +  - ]:          3 :     m_pDoc->Query(0, aParam, true);
    4209                 :            : 
    4210                 :            :     // only row 3 should be hidden.  The rest should be visible.
    4211         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    4212 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 1 & 2 should be visible.", !bHidden && nRow1 == 0 && nRow2 == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4213         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(2, 0, &nRow1, &nRow2);
    4214 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("row 3 should be hidden.", bHidden && nRow1 == 2 && nRow2 == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4215         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(3, 0, &nRow1, &nRow2);
    4216 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("row 4 and down should be visible.", !bHidden && nRow1 == 3 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4217                 :            : 
    4218                 :            :     // Now, filter for empty cells by column C.
    4219         [ +  - ]:          3 :     rEntry.SetQueryByEmpty();
    4220         [ +  - ]:          3 :     m_pDoc->Query(0, aParam, true);
    4221                 :            : 
    4222                 :            :     // Now, only row 1 and 3, and 6 and down should be visible.
    4223         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(0, 0, &nRow1, &nRow2);
    4224 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("row 1 should be visible.", !bHidden && nRow1 == 0 && nRow2 == 0);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4225         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(1, 0, &nRow1, &nRow2);
    4226 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("row 2 should be hidden.", bHidden && nRow1 == 1 && nRow2 == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4227         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(2, 0, &nRow1, &nRow2);
    4228 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("row 3 should be visible.", !bHidden && nRow1 == 2 && nRow2 == 2);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4229         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(3, 0, &nRow1, &nRow2);
    4230 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 4 & 5 should be hidden.", bHidden && nRow1 == 3 && nRow2 == 4);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4231         [ +  - ]:          3 :     bHidden = m_pDoc->RowHidden(5, 0, &nRow1, &nRow2);
    4232 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("rows 6 and down should be all visible.", !bHidden && nRow1 == 5 && nRow2 == MAXROW);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
    4233                 :            : 
    4234 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4235                 :          3 : }
    4236                 :            : 
    4237                 :          3 : void Test::testCopyPaste()
    4238                 :            : {
    4239         [ +  - ]:          3 :     m_pDoc->InsertTab(0, OUString("Sheet1"));
    4240         [ +  - ]:          3 :     m_pDoc->InsertTab(1, OUString("Sheet2"));
    4241                 :            :     //test copy&paste + ScUndoPaste
    4242                 :            :     //copy local and global range names in formulas
    4243                 :            :     //string cells and value cells
    4244         [ +  - ]:          3 :     m_pDoc->SetValue(0, 0, 0, 1);
    4245         [ +  - ]:          3 :     m_pDoc->SetValue(3, 0, 0, 0);
    4246         [ +  - ]:          3 :     m_pDoc->SetValue(3, 1, 0, 1);
    4247         [ +  - ]:          3 :     m_pDoc->SetValue(3, 2, 0, 2);
    4248         [ +  - ]:          3 :     m_pDoc->SetValue(3, 3, 0, 3);
    4249         [ +  - ]:          3 :     m_pDoc->SetString(2, 0, 0, OUString("test"));
    4250                 :          3 :     ScAddress aAdr (0, 0, 0);
    4251                 :            : 
    4252                 :            :     //create some range names, local and global
    4253 [ +  - ][ +  - ]:          3 :     ScRangeData* pLocal1 = new ScRangeData(m_pDoc, rtl::OUString("local1"), aAdr);
    4254 [ +  - ][ +  - ]:          3 :     ScRangeData* pLocal2 = new ScRangeData(m_pDoc, OUString("local2"), aAdr);
    4255 [ +  - ][ +  - ]:          3 :     ScRangeData* pGlobal = new ScRangeData(m_pDoc, OUString("global"), aAdr);
    4256 [ +  - ][ +  - ]:          3 :     ScRangeName* pGlobalRangeName = new ScRangeName();
    4257         [ +  - ]:          3 :     pGlobalRangeName->insert(pGlobal);
    4258 [ +  - ][ +  - ]:          3 :     ScRangeName* pLocalRangeName1 = new ScRangeName();
    4259         [ +  - ]:          3 :     pLocalRangeName1->insert(pLocal1);
    4260         [ +  - ]:          3 :     pLocalRangeName1->insert(pLocal2);
    4261         [ +  - ]:          3 :     m_pDoc->SetRangeName(pGlobalRangeName);
    4262         [ +  - ]:          3 :     m_pDoc->SetRangeName(0, pLocalRangeName1);
    4263                 :            : 
    4264                 :            :     //add formula
    4265                 :          3 :     rtl::OUString aFormulaString("=local1+global+SUM($C$1:$D$4)");
    4266         [ +  - ]:          3 :     m_pDoc->SetString(1, 0, 0, aFormulaString);
    4267                 :            : 
    4268                 :          3 :     double aValue = 0;
    4269         [ +  - ]:          3 :     m_pDoc->GetValue(1, 0, 0, aValue);
    4270 [ +  - ][ +  - ]:          3 :     std::cout << "Value: " << aValue << std::endl;
                 [ +  - ]
    4271 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 8", aValue, 8, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4272                 :            : 
    4273                 :            :     //copy Sheet1.A1:C1 to Sheet2.A2:C2
    4274                 :          3 :     ScRange aRange(0,0,0,2,0,0);
    4275         [ +  - ]:          3 :     ScClipParam aClipParam(aRange, false);
    4276         [ +  - ]:          3 :     ScMarkData aMark;
    4277         [ +  - ]:          3 :     aMark.SetMarkArea(aRange);
    4278 [ +  - ][ +  - ]:          3 :     ScDocument* pClipDoc = new ScDocument(SCDOCMODE_CLIP);
    4279         [ +  - ]:          3 :     m_pDoc->CopyToClip(aClipParam, pClipDoc, &aMark);
    4280                 :            : 
    4281                 :          3 :     sal_uInt16 nFlags = IDF_ALL;
    4282                 :          3 :     aRange = ScRange(0,1,1,2,1,1);//target: Sheet2.A2:C2
    4283 [ +  - ][ +  - ]:          3 :     ScDocument* pUndoDoc = new ScDocument(SCDOCMODE_UNDO);
    4284         [ +  - ]:          3 :     pUndoDoc->InitUndo(m_pDoc, 1, 1, true, true);
    4285         [ +  - ]:          3 :     ScMarkData aMarkData2;
    4286         [ +  - ]:          3 :     aMarkData2.SetMarkArea(aRange);
    4287 [ +  - ][ +  - ]:          3 :     ScRefUndoData* pRefUndoData= new ScRefUndoData(m_pDoc);
    4288                 :            :     SfxUndoAction* pUndo = new ScUndoPaste(
    4289 [ +  - ][ +  - ]:          3 :         &m_xDocShRef, ScRange(0, 1, 1, 2, 1, 1), aMarkData2, pUndoDoc, NULL, IDF_ALL, pRefUndoData, false);
         [ +  - ][ +  - ]
    4290         [ +  - ]:          3 :     m_pDoc->CopyFromClip(aRange, aMarkData2, nFlags, NULL, pClipDoc);
    4291                 :            : 
    4292                 :            :     //check values after copying
    4293                 :          3 :     rtl::OUString aString;
    4294         [ +  - ]:          3 :     m_pDoc->GetValue(1,1,1, aValue);
    4295         [ +  - ]:          3 :     m_pDoc->GetFormula(1,1,1, aString);
    4296 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("copied formula should return 2", aValue, 2, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4297 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("formula string was not copied correctly", aString == aFormulaString);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4298         [ +  - ]:          3 :     m_pDoc->GetValue(0,1,1, aValue);
    4299 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("copied value should be 1", aValue == 1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4300                 :            : 
    4301                 :            :     //chack local range name after copying
    4302 [ +  - ][ +  - ]:          3 :     pLocal1 = m_pDoc->GetRangeName(1)->findByUpperName(OUString("LOCAL1"));
    4303 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("local range name 1 should be copied", pLocal1);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4304                 :          3 :     ScRange aRangeLocal1;
    4305         [ +  - ]:          3 :     pLocal1->IsValidReference(aRangeLocal1);
    4306 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("local range 1 should still point to Sheet1.A1",aRangeLocal1 == ScRange(0,0,0,0,0,0));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4307 [ +  - ][ +  - ]:          3 :     pLocal2 = m_pDoc->GetRangeName(1)->findByUpperName(OUString("LOCAL2"));
    4308 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("local2 should not be copied", pLocal2 == NULL);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4309                 :            : 
    4310                 :            : 
    4311                 :            :     //check undo and redo
    4312         [ +  - ]:          3 :     pUndo->Undo();
    4313         [ +  - ]:          3 :     m_pDoc->GetValue(1,1,1, aValue);
    4314 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after undo formula should return nothing", aValue, 0, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4315         [ +  - ]:          3 :     m_pDoc->GetString(2,1,1, aString);
    4316 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("after undo string should be removed", aString.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("")));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4317                 :            : 
    4318         [ +  - ]:          3 :     pUndo->Redo();
    4319         [ +  - ]:          3 :     m_pDoc->GetValue(1,1,1, aValue);
    4320 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula should return 2 after redo", aValue, 2, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4321         [ +  - ]:          3 :     m_pDoc->GetString(2,1,1, aString);
    4322 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Cell Sheet2.C2 should contain: test", aString.equalsAsciiL(RTL_CONSTASCII_STRINGPARAM("test")));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4323         [ +  - ]:          3 :     m_pDoc->GetFormula(1,1,1, aString);
    4324 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("Formula should be correct again", aString == aFormulaString);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4325                 :            : 
    4326                 :            :     //clear all variables
    4327 [ +  - ][ +  - ]:          3 :     delete pClipDoc;
    4328 [ +  - ][ +  - ]:          3 :     delete pUndoDoc;
    4329         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    4330 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
         [ +  - ][ +  - ]
    4331                 :          3 : }
    4332                 :            : 
    4333                 :          3 : void Test::testMergedCells()
    4334                 :            : {
    4335                 :            :     //test merge and unmerge
    4336                 :            :     //TODO: an undo/redo test for this would be a good idea
    4337         [ +  - ]:          3 :     m_pDoc->InsertTab(0, rtl::OUString("Sheet1"));
    4338         [ +  - ]:          3 :     m_pDoc->DoMerge(0, 1, 1, 3, 3, false);
    4339                 :          3 :     SCCOL nEndCol = 1;
    4340                 :          3 :     SCROW nEndRow = 1;
    4341         [ +  - ]:          3 :     m_pDoc->ExtendMerge( 1, 1, nEndCol, nEndRow, 0, false);
    4342 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("did not merge cells", nEndCol == 3 && nEndRow == 3);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4343                 :          3 :     ScRange aRange(0,2,0,MAXCOL,2,0);
    4344         [ +  - ]:          3 :     ScMarkData aMark;
    4345         [ +  - ]:          3 :     aMark.SetMarkArea(aRange);
    4346                 :          3 :     m_pDoc->SetInTest();
    4347         [ +  - ]:          3 :     m_xDocShRef->GetDocFunc().InsertCells(aRange, &aMark, INS_INSROWS, true, true);
    4348         [ +  - ]:          3 :     m_pDoc->ExtendMerge(1, 1, nEndCol, nEndRow, 0, false);
    4349 [ +  - ][ +  - ]:          3 :     cout << nEndRow << nEndCol;
    4350 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("did not increase merge area", nEndCol == 3 && nEndRow == 4);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4351 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4352                 :          3 : }
    4353                 :            : 
    4354                 :            : 
    4355                 :          3 : void Test::testRenameTable()
    4356                 :            : {
    4357                 :            :     //test set rename table
    4358                 :            :     //TODO: set name1 and name2 and do an undo to check if name 1 is set now
    4359                 :            :     //TODO: also check if new name for table is same as another table
    4360                 :            : 
    4361         [ +  - ]:          3 :     m_pDoc->InsertTab(0, "Sheet1");
    4362         [ +  - ]:          3 :     m_pDoc->InsertTab(1, "Sheet2");
    4363                 :            : 
    4364                 :            :     //test case 1 , rename table2 to sheet 1, it should return error
    4365                 :          3 :     rtl::OUString nameToSet = "Sheet1";
    4366                 :          3 :     ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
    4367 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("name same as another table is being set", !rDocFunc.RenameTable(1,nameToSet,false,true) );
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4368                 :            : 
    4369                 :            :     //test case 2 , simple rename to check name
    4370                 :          3 :     nameToSet = "test1";
    4371 [ +  - ][ +  - ]:          3 :     m_xDocShRef->GetDocFunc().RenameTable(0,nameToSet,false,true);
                 [ +  - ]
    4372                 :          3 :     rtl::OUString nameJustSet;
    4373         [ +  - ]:          3 :     m_pDoc->GetName(0,nameJustSet);
    4374 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("table not renamed", nameToSet != nameJustSet);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4375                 :            : 
    4376                 :            :     //test case 3 , rename again
    4377                 :          3 :     rtl::OUString anOldName;
    4378         [ +  - ]:          3 :     m_pDoc->GetName(0,anOldName);
    4379                 :            : 
    4380                 :          3 :     nameToSet = "test2";
    4381 [ +  - ][ +  - ]:          3 :     rDocFunc.RenameTable(0,nameToSet,false,true);
                 [ +  - ]
    4382         [ +  - ]:          3 :     m_pDoc->GetName(0,nameJustSet);
    4383 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("table not renamed", nameToSet != nameJustSet);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4384                 :            : 
    4385                 :            :     //test case 4 , check if  undo works
    4386 [ +  - ][ +  - ]:          3 :     SfxUndoAction* pUndo = new ScUndoRenameTab(m_xDocShRef,0,anOldName,nameToSet);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4387         [ +  - ]:          3 :     pUndo->Undo();
    4388         [ +  - ]:          3 :     m_pDoc->GetName(0,nameJustSet);
    4389 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the correct name is not set after undo", nameJustSet == anOldName);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4390                 :            : 
    4391         [ +  - ]:          3 :     pUndo->Redo();
    4392         [ +  - ]:          3 :     m_pDoc->GetName(0,nameJustSet);
    4393 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the correct color is not set after redo", nameJustSet == nameToSet);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4394                 :            : 
    4395         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4396         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    4397                 :          3 : }
    4398                 :            : 
    4399                 :            : 
    4400                 :            : 
    4401                 :          3 : void Test::testSetBackgroundColor()
    4402                 :            : {
    4403                 :            :     //test set background color
    4404                 :            :     //TODO: set color1 and set color2 and do an undo to check if color1 is set now.
    4405                 :            : 
    4406         [ +  - ]:          3 :     m_pDoc->InsertTab(0, rtl::OUString("Sheet1"));
    4407                 :          3 :     Color aColor;
    4408                 :            : 
    4409                 :            :      //test yellow
    4410                 :          3 :     aColor=Color(COL_YELLOW);
    4411         [ +  - ]:          3 :     m_xDocShRef->GetDocFunc().SetTabBgColor(0,aColor,false, true);
    4412 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the correct color is not set", m_pDoc->GetTabBgColor(0)!= aColor);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4413                 :            : 
    4414                 :            : 
    4415         [ +  - ]:          3 :     Color aOldTabBgColor=m_pDoc->GetTabBgColor(0);
    4416                 :          3 :     aColor.SetColor(COL_BLUE);//set BLUE
    4417         [ +  - ]:          3 :     m_xDocShRef->GetDocFunc().SetTabBgColor(0,aColor,false, true);
    4418 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the correct color is not set the second time", m_pDoc->GetTabBgColor(0)!= aColor);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4419                 :            : 
    4420                 :            :     //now check for undo
    4421 [ +  - ][ +  - ]:          3 :     SfxUndoAction* pUndo = new ScUndoTabColor(m_xDocShRef,0, aOldTabBgColor, aColor);
    4422         [ +  - ]:          3 :     pUndo->Undo();
    4423 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the correct color is not set after undo", m_pDoc->GetTabBgColor(0)== aOldTabBgColor);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4424         [ +  - ]:          3 :     pUndo->Redo();
    4425 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("the correct color is not set after undo", m_pDoc->GetTabBgColor(0)== aColor);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4426         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4427                 :          3 : }
    4428                 :            : 
    4429                 :            : 
    4430                 :            : 
    4431                 :          3 : void Test::testUpdateReference()
    4432                 :            : {
    4433                 :            :     //test that formulas are correctly updated during sheet delete
    4434                 :            :     //TODO: add tests for relative references, updating of named ranges, ...
    4435                 :          3 :     rtl::OUString aSheet1("Sheet1");
    4436                 :          3 :     rtl::OUString aSheet2("Sheet2");
    4437                 :          3 :     rtl::OUString aSheet3("Sheet3");
    4438                 :          3 :     rtl::OUString aSheet4("Sheet4");
    4439         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aSheet1);
    4440         [ +  - ]:          3 :     m_pDoc->InsertTab(1, aSheet2);
    4441         [ +  - ]:          3 :     m_pDoc->InsertTab(2, aSheet3);
    4442         [ +  - ]:          3 :     m_pDoc->InsertTab(3, aSheet4);
    4443                 :            : 
    4444         [ +  - ]:          3 :     m_pDoc->SetValue(0,0,2, 1);
    4445         [ +  - ]:          3 :     m_pDoc->SetValue(1,0,2, 2);
    4446         [ +  - ]:          3 :     m_pDoc->SetValue(1,1,3, 4);
    4447         [ +  - ]:          3 :     m_pDoc->SetString(2,0,2, rtl::OUString("=A1+B1"));
    4448         [ +  - ]:          3 :     m_pDoc->SetString(2,1,2, rtl::OUString("=Sheet4.B2+A1"));
    4449                 :            : 
    4450                 :            :     double aValue;
    4451         [ +  - ]:          3 :     m_pDoc->GetValue(2,0,2, aValue);
    4452 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4453         [ +  - ]:          3 :     m_pDoc->GetValue(2,1,2, aValue);
    4454 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("formula does not return correct result", aValue == 5);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4455                 :            : 
    4456                 :            :     //test deleting both sheets: one is not directly before the sheet, the other one is
    4457         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4458         [ +  - ]:          3 :     m_pDoc->GetValue(2,0,1, aValue);
    4459 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4460         [ +  - ]:          3 :     m_pDoc->GetValue(2,1,1, aValue);
    4461 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting first sheet formula does not return correct result", aValue, 5, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4462                 :            : 
    4463         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4464         [ +  - ]:          3 :     m_pDoc->GetValue(2,0,0, aValue);
    4465 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4466         [ +  - ]:          3 :     m_pDoc->GetValue(2,1,0, aValue);
    4467 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting second sheet formula does not return correct result", aValue, 5, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4468                 :            : 
    4469                 :            :     //test adding two sheets
    4470         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aSheet2);
    4471         [ +  - ]:          3 :     m_pDoc->GetValue(2,0,1, aValue);
    4472 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4473         [ +  - ]:          3 :     m_pDoc->GetValue(2,1,1, aValue);
    4474 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting first sheet formula does not return correct result", aValue, 5, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4475                 :            : 
    4476         [ +  - ]:          3 :     m_pDoc->InsertTab(0, aSheet1);
    4477         [ +  - ]:          3 :     m_pDoc->GetValue(2,0,2, aValue);
    4478 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4479         [ +  - ]:          3 :     m_pDoc->GetValue(2,1,2, aValue);
    4480 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting second sheet formula does not return correct result", aValue, 5, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4481                 :            : 
    4482                 :            :     //test new DeleteTabs/InsertTabs methods
    4483         [ +  - ]:          3 :     m_pDoc->DeleteTabs(0, 2);
    4484         [ +  - ]:          3 :     m_pDoc->GetValue(2, 0, 0, aValue);
    4485 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4486         [ +  - ]:          3 :     m_pDoc->GetValue(2, 1, 0, aValue);
    4487 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after deleting sheets formula does not return correct result", aValue, 5, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4488                 :            : 
    4489         [ +  - ]:          3 :     std::vector<rtl::OUString> aSheets;
    4490         [ +  - ]:          3 :     aSheets.push_back(aSheet1);
    4491         [ +  - ]:          3 :     aSheets.push_back(aSheet2);
    4492         [ +  - ]:          3 :     m_pDoc->InsertTabs(0, aSheets, false, true);
    4493         [ +  - ]:          3 :     m_pDoc->GetValue(2, 0, 2, aValue);
    4494                 :          3 :     rtl::OUString aFormula;
    4495         [ +  - ]:          3 :     m_pDoc->GetFormula(2,0,2, aFormula);
    4496 [ +  - ][ +  - ]:          3 :     std::cout << "formel: " << rtl::OUStringToOString(aFormula, RTL_TEXTENCODING_UTF8).getStr() << std::endl;
         [ +  - ][ +  - ]
    4497 [ +  - ][ +  - ]:          3 :     std::cout << std::endl << aValue << std::endl;
                 [ +  - ]
    4498 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 3, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4499         [ +  - ]:          3 :     m_pDoc->GetValue(2, 1, 2, aValue);
    4500 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE("after inserting sheets formula does not return correct result", aValue, 5, 0.00000001);
         [ +  - ][ +  - ]
                 [ +  - ]
    4501                 :            : 
    4502         [ +  - ]:          3 :     m_pDoc->DeleteTab(3);
    4503         [ +  - ]:          3 :     m_pDoc->DeleteTab(2);
    4504         [ +  - ]:          3 :     m_pDoc->DeleteTab(1);
    4505         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4506                 :          3 : }
    4507                 :            : 
    4508                 :            : namespace {
    4509                 :            : 
    4510                 :         12 : bool hasRange(const std::vector<ScTokenRef>& rRefTokens, const ScRange& rRange)
    4511                 :            : {
    4512                 :         12 :     std::vector<ScTokenRef>::const_iterator it = rRefTokens.begin(), itEnd = rRefTokens.end();
    4513 [ +  - ][ +  - ]:         15 :     for (; it != itEnd; ++it)
    4514                 :            :     {
    4515                 :         15 :         const ScTokenRef& p = *it;
    4516 [ +  - ][ +  - ]:         15 :         if (!ScRefTokenHelper::isRef(p) || ScRefTokenHelper::isExternalRef(p))
         [ -  + ][ -  + ]
                 [ +  - ]
    4517                 :          0 :             continue;
    4518                 :            : 
    4519      [ +  +  - ]:         15 :         switch (p->GetType())
    4520                 :            :         {
    4521                 :            :             case formula::svSingleRef:
    4522                 :            :             {
    4523         [ +  - ]:          6 :                 ScSingleRefData aData = p->GetSingleRef();
    4524         [ +  - ]:          6 :                 if (rRange.aStart != rRange.aEnd)
    4525                 :            :                     break;
    4526                 :            : 
    4527                 :          6 :                 ScAddress aThis(aData.nCol, aData.nRow, aData.nTab);
    4528         [ +  - ]:          6 :                 if (aThis == rRange.aStart)
    4529                 :          6 :                     return true;
    4530                 :            :             }
    4531                 :          0 :             break;
    4532                 :            :             case formula::svDoubleRef:
    4533                 :            :             {
    4534         [ +  - ]:          9 :                 ScComplexRefData aData = p->GetDoubleRef();
    4535                 :          9 :                 ScRange aThis(aData.Ref1.nCol, aData.Ref1.nRow, aData.Ref1.nTab, aData.Ref2.nCol, aData.Ref2.nRow, aData.Ref2.nTab);
    4536         [ +  + ]:          9 :                 if (aThis == rRange)
    4537                 :          6 :                     return true;
    4538                 :            :             }
    4539                 :          3 :             break;
    4540                 :            :             default:
    4541                 :            :                 ;
    4542                 :            :         }
    4543                 :            :     }
    4544                 :         12 :     return false;
    4545                 :            : }
    4546                 :            : 
    4547                 :            : }
    4548                 :            : 
    4549                 :          3 : void Test::testJumpToPrecedentsDependents()
    4550                 :            : {
    4551                 :            :     // Precedent is another cell that the cell references, while dependent is
    4552                 :            :     // another cell that references it.
    4553         [ +  - ]:          3 :     m_pDoc->InsertTab(0, rtl::OUString("Test"));
    4554                 :            : 
    4555         [ +  - ]:          3 :     m_pDoc->SetString(2, 0, 0, rtl::OUString("=A1+A2+B3")); // C1
    4556         [ +  - ]:          3 :     m_pDoc->SetString(2, 1, 0, rtl::OUString("=A1"));       // C2
    4557         [ +  - ]:          3 :     m_pDoc->CalcAll();
    4558                 :            : 
    4559         [ +  - ]:          3 :     std::vector<ScTokenRef> aRefTokens;
    4560                 :          3 :     ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
    4561                 :            : 
    4562                 :            :     {
    4563                 :            :         // C1's precedent should be A1:A2,B3.
    4564         [ +  - ]:          3 :         ScRangeList aRange(ScRange(2, 0, 0));
    4565         [ +  - ]:          3 :         rDocFunc.DetectiveCollectAllPreds(aRange, aRefTokens);
    4566 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("A1:A2 should be a precedent of C1.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4567         [ +  - ]:          3 :                                hasRange(aRefTokens, ScRange(0, 0, 0, 0, 1, 0)));
    4568 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("B3 should be a precedent of C1.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4569   [ +  -  +  - ]:          6 :                                hasRange(aRefTokens, ScRange(1, 2, 0)));
    4570                 :            :     }
    4571                 :            : 
    4572                 :            :     {
    4573                 :            :         // C2's precedent should be A1 only.
    4574         [ +  - ]:          3 :         ScRangeList aRange(ScRange(2, 1, 0));
    4575         [ +  - ]:          3 :         rDocFunc.DetectiveCollectAllPreds(aRange, aRefTokens);
    4576 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_EQUAL_MESSAGE("there should only be one reference token.",
         [ +  - ][ +  - ]
    4577         [ +  - ]:          3 :                                aRefTokens.size(), static_cast<size_t>(1));
    4578 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("A1 should be a precedent of C1.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4579   [ +  -  +  - ]:          6 :                                hasRange(aRefTokens, ScRange(0, 0, 0)));
    4580                 :            :     }
    4581                 :            : 
    4582                 :            :     {
    4583                 :            :         // A1's dependent should be C1:C2.
    4584         [ +  - ]:          3 :         ScRangeList aRange(ScRange(0, 0, 0));
    4585         [ +  - ]:          3 :         rDocFunc.DetectiveCollectAllSuccs(aRange, aRefTokens);
    4586 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_MESSAGE("C1:C2 should be the only dependent of A1.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
                 [ #  # ]
    4587   [ +  -  +  - ]:          6 :                                aRefTokens.size() == 1 && hasRange(aRefTokens, ScRange(2, 0, 0, 2, 1, 0)));
    4588                 :            :     }
    4589                 :            : 
    4590         [ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4591                 :          3 : }
    4592                 :            : 
    4593                 :          3 : void Test::testAutoFill()
    4594                 :            : {
    4595         [ +  - ]:          3 :     m_pDoc->InsertTab(0, "test");
    4596                 :            : 
    4597         [ +  - ]:          3 :     m_pDoc->SetValue(0,0,0,1);
    4598                 :            : 
    4599         [ +  - ]:          3 :     ScMarkData aMarkData;
    4600         [ +  - ]:          3 :     aMarkData.SelectTable(0, true);
    4601                 :            : 
    4602         [ +  - ]:          3 :     m_pDoc->Fill( 0, 0, 0, 0, NULL, aMarkData, 5);
    4603         [ +  + ]:         21 :     for (SCROW i = 0; i< 6; ++i)
    4604 [ +  - ][ +  - ]:         18 :         CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1.0), m_pDoc->GetValue(0, i, 0), 0.00000001);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4605                 :            : 
    4606                 :            :     // check that hidden rows are not affected by autofill
    4607                 :            :     // set values for hidden rows
    4608         [ +  - ]:          3 :     m_pDoc->SetValue(0,1,0,10);
    4609         [ +  - ]:          3 :     m_pDoc->SetValue(0,2,0,10);
    4610                 :            : 
    4611         [ +  - ]:          3 :     m_pDoc->SetRowHidden(1, 2, 0, true);
    4612         [ +  - ]:          3 :     m_pDoc->Fill( 0, 0, 0, 0, NULL, aMarkData, 8);
    4613                 :            : 
    4614 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,1,0), 1e-08);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4615 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,2,0), 1e-08);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4616         [ +  + ]:         18 :     for (SCROW i = 3; i< 8; ++i)
    4617 [ +  - ][ +  - ]:         15 :         CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i-1.0), m_pDoc->GetValue(0, i, 0), 0.00000001);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4618                 :            : 
    4619         [ +  - ]:          3 :     m_pDoc->Fill( 0, 0, 0, 8, NULL, aMarkData, 5, FILL_TO_RIGHT );
    4620         [ +  + ]:         18 :     for (SCCOL i = 0; i < 5; ++i)
    4621                 :            :     {
    4622         [ +  + ]:        135 :         for(SCROW j = 0; j < 8; ++j)
    4623                 :            :         {
    4624         [ +  + ]:        120 :             if (j > 2)
    4625                 :            :             {
    4626 [ +  - ][ +  - ]:         75 :                 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(j-1+i), m_pDoc->GetValue(i, j, 0), 1e-8);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4627                 :            :             }
    4628         [ +  + ]:         45 :             else if (j == 0)
    4629                 :            :             {
    4630 [ +  - ][ +  - ]:         15 :                 CPPUNIT_ASSERT_DOUBLES_EQUAL(static_cast<double>(i+1), m_pDoc->GetValue(i, 0, 0), 1e-8);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4631                 :            :             }
    4632 [ +  + ][ +  - ]:         30 :             else if (j == 1 || j== 2)
    4633                 :            :             {
    4634         [ +  + ]:         30 :                 if(i == 0)
    4635 [ +  - ][ +  - ]:          6 :                     CPPUNIT_ASSERT_DOUBLES_EQUAL(10.0, m_pDoc->GetValue(0,j,0), 1e-8);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4636                 :            :                 else
    4637 [ +  - ][ +  - ]:         24 :                     CPPUNIT_ASSERT_DOUBLES_EQUAL(0.0, m_pDoc->GetValue(i,j,0), 1e-8);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4638                 :            :             }
    4639                 :            :         }
    4640                 :            :     }
    4641                 :            : 
    4642                 :            :     // test auto fill user data lists
    4643         [ +  - ]:          3 :     m_pDoc->SetString( 0, 100, 0, "January" );
    4644         [ +  - ]:          3 :     m_pDoc->Fill( 0, 100, 0, 100, NULL, aMarkData, 2, FILL_TO_BOTTOM, FILL_AUTO );
    4645         [ +  - ]:          3 :     rtl::OUString aTestValue = m_pDoc->GetString( 0, 101, 0 );
    4646 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL( aTestValue, rtl::OUString("February") );
         [ +  - ][ +  - ]
                 [ +  - ]
    4647         [ +  - ]:          3 :     aTestValue = m_pDoc->GetString( 0, 102, 0 );
    4648 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL( aTestValue, rtl::OUString("March") );
         [ +  - ][ +  - ]
                 [ +  - ]
    4649                 :            : 
    4650                 :            :     // test that two same user data list entries will not result in incremental fill
    4651         [ +  - ]:          3 :     m_pDoc->SetString( 0, 101, 0, "January" );
    4652         [ +  - ]:          3 :     m_pDoc->Fill( 0, 100, 0, 101, NULL, aMarkData, 2, FILL_TO_BOTTOM, FILL_AUTO );
    4653         [ +  + ]:          9 :     for ( SCROW i = 102; i <= 103; ++i )
    4654                 :            :     {
    4655         [ +  - ]:          6 :         aTestValue = m_pDoc->GetString( 0, i, 0 );
    4656 [ +  - ][ +  - ]:          6 :         CPPUNIT_ASSERT_EQUAL( aTestValue, rtl::OUString("January") );
         [ +  - ][ +  - ]
                 [ +  - ]
    4657                 :            :     }
    4658 [ +  - ][ +  - ]:          3 :     m_pDoc->DeleteTab(0);
    4659                 :          3 : }
    4660                 :            : 
    4661                 :          3 : void Test::testCopyPasteFormulas()
    4662                 :            : {
    4663         [ +  - ]:          3 :     m_pDoc->InsertTab(0, "Sheet1");
    4664         [ +  - ]:          3 :     m_pDoc->InsertTab(1, "Sheet2");
    4665                 :            : 
    4666         [ +  - ]:          3 :     m_pDoc->SetString(0,0,0, "=COLUMN($A$1)");
    4667         [ +  - ]:          3 :     m_pDoc->SetString(0,1,0, "=$A$1+B2" );
    4668         [ +  - ]:          3 :     m_pDoc->SetString(0,2,0, "=$Sheet2.A1");
    4669         [ +  - ]:          3 :     m_pDoc->SetString(0,3,0, "=$Sheet2.$A$1");
    4670         [ +  - ]:          3 :     m_pDoc->SetString(0,4,0, "=$Sheet2.A$1");
    4671                 :            : 
    4672                 :            :     // to prevent ScEditableTester in ScDocFunc::MoveBlock
    4673                 :          3 :     m_pDoc->SetInTest();
    4674 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,0,0), 1.0, 1e-08);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4675 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(0,1,0), 1.0, 1e-08);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4676                 :          3 :     ScDocFunc& rDocFunc = m_xDocShRef->GetDocFunc();
    4677         [ +  - ]:          3 :     bool bMoveDone = rDocFunc.MoveBlock(ScRange(0,0,0,0,4,0), ScAddress( 10, 10, 0), false, false, false, true);
    4678                 :            : 
    4679                 :            :     // check that moving was succesful, mainly for editable tester
    4680 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT(bMoveDone);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4681 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,10,0), 1.0, 1e-8);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4682 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_DOUBLES_EQUAL(m_pDoc->GetValue(10,11,0), 1.0, 1e-8);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4683                 :          3 :     rtl::OUString aFormula;
    4684         [ +  - ]:          3 :     m_pDoc->GetFormula(10,10,0, aFormula);
    4685 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=COLUMN($A$1)"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4686         [ +  - ]:          3 :     m_pDoc->GetFormula(10,11,0, aFormula);
    4687 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$A$1+L12"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4688         [ +  - ]:          3 :     m_pDoc->GetFormula(10,12,0, aFormula);
    4689 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$Sheet2.K11"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4690         [ +  - ]:          3 :     m_pDoc->GetFormula(10,13,0, aFormula);
    4691 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$Sheet2.$A$1"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4692         [ +  - ]:          3 :     m_pDoc->GetFormula(10,14,0, aFormula);
    4693 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$Sheet2.K$1"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4694                 :          3 : }
    4695                 :            : 
    4696                 :          3 : void Test::testCopyPasteFormulasExternalDoc()
    4697                 :            : {
    4698                 :          3 :     rtl::OUString aDocName("file:///source.fake");
    4699 [ +  - ][ +  - ]:          3 :     SfxMedium* pMedium = new SfxMedium(aDocName, STREAM_STD_READWRITE);
         [ +  - ][ +  - ]
    4700         [ +  - ]:          3 :     m_xDocShRef->DoInitNew(pMedium);
    4701                 :          3 :     m_pDoc = m_xDocShRef->GetDocument();
    4702                 :            : 
    4703 [ +  - ][ +  - ]:          3 :     ScDocShellRef xExtDocSh = new ScDocShell;
    4704                 :          3 :     OUString aExtDocName("file:///extdata.fake");
    4705                 :          3 :     OUString aExtSh1Name("ExtSheet1");
    4706                 :          3 :     OUString aExtSh2Name("ExtSheet2");
    4707 [ +  - ][ +  - ]:          3 :     SfxMedium* pMed = new SfxMedium(aExtDocName, STREAM_STD_READWRITE);
         [ +  - ][ +  - ]
    4708         [ +  - ]:          3 :     xExtDocSh->DoInitNew(pMed);
    4709 [ +  - ][ +  - ]:          6 :     CPPUNIT_ASSERT_MESSAGE("external document instance not loaded.",
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4710         [ +  - ]:          3 :                            findLoadedDocShellByName(aExtDocName) != NULL);
    4711                 :            : 
    4712                 :          3 :     ScDocument* pExtDoc = xExtDocSh->GetDocument();
    4713         [ +  - ]:          3 :     pExtDoc->InsertTab(0, aExtSh1Name);
    4714         [ +  - ]:          3 :     pExtDoc->InsertTab(1, aExtSh2Name);
    4715                 :            : 
    4716         [ +  - ]:          3 :     m_pDoc->InsertTab(0, "Sheet1");
    4717         [ +  - ]:          3 :     m_pDoc->InsertTab(1, "Sheet2");
    4718                 :            : 
    4719         [ +  - ]:          3 :     m_pDoc->SetString(0,0,0, "=COLUMN($A$1)");
    4720         [ +  - ]:          3 :     m_pDoc->SetString(0,1,0, "=$A$1+B2" );
    4721         [ +  - ]:          3 :     m_pDoc->SetString(0,2,0, "=$Sheet2.A1");
    4722         [ +  - ]:          3 :     m_pDoc->SetString(0,3,0, "=$Sheet2.$A$1");
    4723         [ +  - ]:          3 :     m_pDoc->SetString(0,4,0, "=$Sheet2.A$1");
    4724         [ +  - ]:          3 :     m_pDoc->SetString(0,5,0, "=$Sheet1.$A$1");
    4725                 :            : 
    4726                 :          3 :     ScRange aRange(0,0,0,0,5,0);
    4727         [ +  - ]:          3 :     ScClipParam aClipParam(aRange, false);
    4728         [ +  - ]:          3 :     ScMarkData aMark;
    4729         [ +  - ]:          3 :     aMark.SetMarkArea(aRange);
    4730 [ +  - ][ +  - ]:          3 :     ScDocument* pClipDoc = new ScDocument(SCDOCMODE_CLIP);
    4731         [ +  - ]:          3 :     m_pDoc->CopyToClip(aClipParam, pClipDoc, &aMark);
    4732                 :            : 
    4733                 :          3 :     sal_uInt16 nFlags = IDF_ALL;
    4734                 :          3 :     aRange = ScRange(1,1,1,1,6,1);
    4735         [ +  - ]:          3 :     ScMarkData aMarkData2;
    4736         [ +  - ]:          3 :     aMarkData2.SetMarkArea(aRange);
    4737         [ +  - ]:          3 :     pExtDoc->CopyFromClip(aRange, aMarkData2, nFlags, NULL, pClipDoc);
    4738                 :            : 
    4739                 :          3 :     rtl::OUString aFormula;
    4740         [ +  - ]:          3 :     pExtDoc->GetFormula(1,1,1, aFormula);
    4741                 :            :     //adjust absolute refs pointing to the copy area
    4742 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=COLUMN($B$2)"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4743         [ +  - ]:          3 :     pExtDoc->GetFormula(1,2,1, aFormula);
    4744                 :            :     //adjust absolute refs and keep relative refs
    4745 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$B$2+C3"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4746         [ +  - ]:          3 :     pExtDoc->GetFormula(1,3,1, aFormula);
    4747                 :            :     // make absolute sheet refs external refs
    4748 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("='file:///source.fake'#$Sheet2.B2"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4749         [ +  - ]:          3 :     pExtDoc->GetFormula(1,4,1, aFormula);
    4750 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("='file:///source.fake'#$Sheet2.$A$1"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4751         [ +  - ]:          3 :     pExtDoc->GetFormula(1,5,1, aFormula);
    4752 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("='file:///source.fake'#$Sheet2.B$1"));
         [ +  - ][ +  - ]
                 [ +  - ]
    4753         [ +  - ]:          3 :     pExtDoc->GetFormula(1,6,1, aFormula);
    4754 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(aFormula, rtl::OUString("=$ExtSheet2.$B$2"));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4755                 :          3 : }
    4756                 :            : 
    4757                 :          3 : void Test::testFindAreaPosRowDown()
    4758                 :            : {
    4759                 :            :     const char* aData[][2] = {
    4760                 :            :         { "", "1" },
    4761                 :            :         { "1", "" },
    4762                 :            :         { "1", "1" },
    4763                 :            :         { "", "1" },
    4764                 :            :         { "1", "1" },
    4765                 :            :         { "1", "" },
    4766                 :          3 :         { "1", "1" }, };
    4767                 :            : 
    4768                 :          3 :     ScDocument* pDoc = m_xDocShRef->GetDocument();
    4769                 :          3 :     rtl::OUString aTabName1("test1");
    4770         [ +  - ]:          3 :     pDoc->InsertTab(0, aTabName1);
    4771         [ +  - ]:          3 :     clearRange( pDoc, ScRange(0, 0, 0, 1, SAL_N_ELEMENTS(aData), 0));
    4772                 :          3 :     ScAddress aPos(0,0,0);
    4773         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData( pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    4774 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4775                 :            : 
    4776         [ +  - ]:          3 :     pDoc->SetRowHidden(4,4,0,true);
    4777         [ +  - ]:          3 :     bool bHidden = pDoc->RowHidden(4,0);
    4778 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT(bHidden);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4779                 :            : 
    4780                 :          3 :     SCCOL nCol = 0;
    4781                 :          3 :     SCROW nRow = 0;
    4782         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4783                 :            : 
    4784 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4785 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4786                 :            : 
    4787         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4788                 :            : 
    4789 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(2), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4790 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4791                 :            : 
    4792         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4793                 :            : 
    4794 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(5), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4795 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4796                 :            : 
    4797         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4798                 :            : 
    4799 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4800 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4801                 :            : 
    4802         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4803                 :            : 
    4804 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(MAXROW), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4805 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(0), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4806                 :            : 
    4807                 :          3 :     nCol = 1;
    4808                 :          3 :     nRow = 2;
    4809                 :            : 
    4810         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4811                 :            : 
    4812 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(3), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4813 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4814                 :            : 
    4815         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_DOWN);
    4816                 :            : 
    4817 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(6), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4818 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4819                 :            : 
    4820         [ +  - ]:          3 :     pDoc->DeleteTab(0);
    4821                 :          3 : }
    4822                 :            : 
    4823                 :          3 : void Test::testFindAreaPosColRight()
    4824                 :            : {
    4825                 :            :     const char* aData[][7] = {
    4826                 :            :         { "", "1", "1", "", "1", "1", "1" },
    4827                 :          3 :         { "", "", "1", "1", "1", "", "1" }, };
    4828                 :            : 
    4829                 :          3 :     ScDocument* pDoc = m_xDocShRef->GetDocument();
    4830                 :          3 :     rtl::OUString aTabName1("test1");
    4831         [ +  - ]:          3 :     pDoc->InsertTab(0, aTabName1);
    4832         [ +  - ]:          3 :     clearRange( pDoc, ScRange(0, 0, 0, 7, SAL_N_ELEMENTS(aData), 0));
    4833                 :          3 :     ScAddress aPos(0,0,0);
    4834         [ +  - ]:          3 :     ScRange aDataRange = insertRangeData( pDoc, aPos, aData, SAL_N_ELEMENTS(aData));
    4835 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_MESSAGE("failed to insert range data at correct position", aDataRange.aStart == aPos);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    4836                 :            : 
    4837         [ +  - ]:          3 :     pDoc->SetColHidden(4,4,0,true);
    4838         [ +  - ]:          3 :     bool bHidden = pDoc->ColHidden(4,0);
    4839 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT(bHidden);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
    4840                 :            : 
    4841                 :          3 :     SCCOL nCol = 0;
    4842                 :          3 :     SCROW nRow = 0;
    4843         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4844                 :            : 
    4845 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4846 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(1), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4847                 :            : 
    4848         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4849                 :            : 
    4850 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4851 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(2), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4852                 :            : 
    4853         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4854                 :            : 
    4855 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4856 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(5), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4857                 :            : 
    4858         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4859                 :            : 
    4860 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4861 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(6), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4862                 :            : 
    4863         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4864                 :            : 
    4865 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(0), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4866 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(MAXCOL), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4867                 :            : 
    4868                 :          3 :     nCol = 2;
    4869                 :          3 :     nRow = 1;
    4870                 :            : 
    4871         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4872                 :            : 
    4873 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4874 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(3), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4875                 :            : 
    4876         [ +  - ]:          3 :     pDoc->FindAreaPos(nCol, nRow, 0, SC_MOVE_RIGHT);
    4877                 :            : 
    4878 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCROW>(1), nRow);
         [ +  - ][ +  - ]
                 [ +  - ]
    4879 [ +  - ][ +  - ]:          3 :     CPPUNIT_ASSERT_EQUAL(static_cast<SCCOL>(6), nCol);
         [ +  - ][ +  - ]
                 [ +  - ]
    4880                 :            : 
    4881         [ +  - ]:          3 :     pDoc->DeleteTab(0);
    4882                 :          3 : }
    4883                 :            : 
    4884                 :          3 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
    4885                 :            : 
    4886                 :            : }
    4887                 :            : 
    4888 [ +  - ][ +  - ]:         12 : CPPUNIT_PLUGIN_IMPLEMENT();
         [ +  - ][ +  - ]
         [ +  - ][ #  # ]
    4889                 :            : 
    4890                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10