LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/sc/qa/unit/helper - qahelper.hxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 134 155 86.5 %
Date: 2013-07-09 Functions: 15 18 83.3 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  */
       9             : 
      10             : #ifndef SC_QA_HELPER_HXX
      11             : #define SC_QA_HELPER_HXX
      12             : 
      13             : #include <test/bootstrapfixture.hxx>
      14             : #define __ORCUS_STATIC_LIB
      15             : #include "helper/csv_handler.hxx"
      16             : #include "helper/debughelper.hxx"
      17             : #include "orcus/csv_parser.hpp"
      18             : #include <fstream>
      19             : #include <string>
      20             : #include <sstream>
      21             : 
      22             : #include <comphelper/documentconstants.hxx>
      23             : 
      24             : #include <osl/detail/android-bootstrap.h>
      25             : 
      26             : #include <unotools/tempfile.hxx>
      27             : #include <comphelper/storagehelper.hxx>
      28             : #include <sfx2/docfilt.hxx>
      29             : 
      30             : #define ODS_FORMAT_TYPE 50331943
      31             : #define XLS_FORMAT_TYPE 318767171
      32             : #define XLSX_FORMAT_TYPE 268959811
      33             : #define LOTUS123_FORMAT_TYPE 268435649
      34             : #define CSV_FORMAT_TYPE  (SFX_FILTER_IMPORT | SFX_FILTER_EXPORT | SFX_FILTER_ALIEN | SFX_FILTER_USESOPTIONS)
      35             : #define HTML_FORMAT_TYPE (SFX_FILTER_IMPORT | SFX_FILTER_EXPORT | SFX_FILTER_ALIEN | SFX_FILTER_USESOPTIONS)
      36             : #define DIF_FORMAT_TYPE 195
      37             : 
      38             : #define ODS      0
      39             : #define XLS      1
      40             : #define XLSX     2
      41             : #define CSV      3
      42             : #define HTML     4
      43             : #define LOTUS123 5
      44             : #define DIF      6
      45             : 
      46          26 : bool testEqualsWithTolerance( long nVal1, long nVal2, long nTol )
      47             : {
      48          26 :     return ( labs( nVal1 - nVal2 ) <= nTol );
      49             : }
      50             : 
      51             : struct FileFormat {
      52             :     const char* pName; const char* pFilterName; const char* pTypeName; unsigned int nFormatType;
      53             : };
      54             : 
      55             : #define CHECK_OPTIMAL 0x1
      56             : 
      57             : // data format for row height tests
      58             : struct TestParam
      59             : {
      60             :     struct RowData
      61             :     {
      62             :         SCROW nStartRow;
      63             :         SCROW nEndRow;
      64             :         SCTAB nTab;
      65             :         int nExpectedHeight; // -1 for default height
      66             :         int nCheck; // currently only CHECK_OPTIMAL ( we could add CHECK_MANUAL etc.)
      67             :         bool bOptimal;
      68             :     };
      69             :     const char* sTestDoc;
      70             :     int nImportType;
      71             :     int nExportType; // -1 for import test, otherwise this is an export test
      72             :     int nRowData;
      73             :     RowData* pData;
      74             : };
      75             : 
      76             : FileFormat aFileFormats[] = {
      77             :     { "ods" , "calc8", "", ODS_FORMAT_TYPE },
      78             :     { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE },
      79             :     { "xlsx", "Calc MS Excel 2007 XML" , "MS Excel 2007 XML", XLSX_FORMAT_TYPE },
      80             :     { "csv" , "Text - txt - csv (StarCalc)", "generic_Text", CSV_FORMAT_TYPE },
      81             :     { "html" , "calc_HTML_WebQuery", "generic_HTML", HTML_FORMAT_TYPE },
      82             :     { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE },
      83             :     { "dif", "DIF", "calc_DIF", DIF_FORMAT_TYPE },
      84             : };
      85             : 
      86             : // Why is this here and not in osl, and using the already existing file
      87             : // handling APIs? Do we really want to add arbitrary new file handling
      88             : // wrappers here and there (and then having to handle the Android (and
      89             : // eventually perhaps iOS) special cases here, too)?  Please move this to osl,
      90             : // it sure looks gemerally useful. Or am I missing something?
      91             : 
      92          33 : void loadFile(const OUString& aFileName, std::string& aContent)
      93             : {
      94          33 :     OString aOFileName = OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8);
      95             : 
      96             : #ifdef ANDROID
      97             :     size_t size;
      98             :     if (strncmp(aOFileName.getStr(), "/assets/", sizeof("/assets/")-1) == 0) {
      99             :         const char *contents = (const char *) lo_apkentry(aOFileName.getStr(), &size);
     100             :         if (contents != 0) {
     101             :             aContent = std::string(contents, size);
     102             :             return;
     103             :         }
     104             :     }
     105             : #endif
     106             : 
     107          66 :     std::ifstream aFile(aOFileName.getStr());
     108             : 
     109          66 :     OStringBuffer aErrorMsg("Could not open csv file: ");
     110          33 :     aErrorMsg.append(aOFileName);
     111          33 :     CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), aFile);
     112          66 :     std::ostringstream aOStream;
     113          33 :     aOStream << aFile.rdbuf();
     114          33 :     aFile.close();
     115          66 :     aContent = aOStream.str();
     116          33 : }
     117             : 
     118           0 : std::string print(const ScAddress& rAddr)
     119             : {
     120           0 :     std::stringstream str;
     121           0 :     str << "Col: " << rAddr.Col();
     122           0 :     str << " Row: " << rAddr.Row();
     123           0 :     str << " Tab: " << rAddr.Tab();
     124           0 :     return str.str();
     125             : }
     126             : 
     127             : namespace CppUnit {
     128             : 
     129             : template<>
     130             : struct assertion_traits<ScRange>
     131             : {
     132           2 :     static bool equal( const ScRange& x, const ScRange& y )
     133             :     {
     134           2 :         return x == y;
     135             :     }
     136             : 
     137           0 :     static std::string toString( const ScRange& x )
     138             :     {
     139           0 :         std::stringstream str;
     140           0 :         str << "Start: " << print(x.aStart);
     141           0 :         str << "\nEnd: " << print(x.aEnd);
     142           0 :         return str.str();
     143             :     }
     144             : };
     145             : 
     146             : }
     147             : 
     148          63 : class ScBootstrapFixture : public test::BootstrapFixture
     149             : {
     150             : protected:
     151             :     OUString m_aBaseString;
     152          98 :     ScDocShellRef load( bool bReadWrite,
     153             :         const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
     154             :         const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID,  sal_uIntPtr nFilterVersion = SOFFICE_FILEFORMAT_CURRENT, const OUString* pPassword = NULL )
     155             :     {
     156             :         SfxFilter* pFilter = new SfxFilter(
     157             :             rFilter,
     158             :             OUString(), nFilterFlags, nClipboardID, rTypeName, 0, OUString(),
     159          98 :             rUserData, OUString("private:factory/scalc*"));
     160          98 :         pFilter->SetVersion(nFilterVersion);
     161             : 
     162          98 :         ScDocShellRef xDocShRef = new ScDocShell;
     163          98 :         xDocShRef->GetDocument()->EnableUserInteraction(false);
     164          98 :         SfxMedium* pSrcMed = new SfxMedium(rURL, bReadWrite ? STREAM_STD_READWRITE : STREAM_STD_READ );
     165          98 :         pSrcMed->SetFilter(pFilter);
     166          98 :         pSrcMed->UseInteractionHandler(false);
     167          98 :         if (pPassword)
     168             :         {
     169           1 :             SfxItemSet* pSet = pSrcMed->GetItemSet();
     170           1 :             pSet->Put(SfxStringItem(SID_PASSWORD, *pPassword));
     171             :         }
     172          98 :         printf("about to load %s\n", OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
     173          98 :         if (!xDocShRef->DoLoad(pSrcMed))
     174             :         {
     175           3 :             xDocShRef->DoClose();
     176             :             // load failed.
     177           3 :             xDocShRef.Clear();
     178             :         }
     179             : 
     180          98 :         return xDocShRef;
     181             :     }
     182             : 
     183          35 :     ScDocShellRef load(
     184             :         const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
     185             :         const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID,  sal_uIntPtr nFilterVersion = SOFFICE_FILEFORMAT_CURRENT, const OUString* pPassword = NULL )
     186             :     {
     187          35 :         return load( false, rURL, rFilter, rUserData, rTypeName, nFilterFlags, nClipboardID,  nFilterVersion, pPassword );
     188             :     }
     189             : 
     190          63 :     ScDocShellRef loadDoc(const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite = false )
     191             :     {
     192          63 :         OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
     193         126 :         OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
     194         126 :         OUString aFileName;
     195          63 :         createFileURL( rFileName, aFileExtension, aFileName );
     196         126 :         OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
     197          63 :         unsigned int nFormatType = aFileFormats[nFormat].nFormatType;
     198          63 :         unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
     199             : 
     200         126 :         return load(bReadWrite, aFileName, aFilterName, OUString(), aFilterType, nFormatType, nClipboardId, nFormatType);
     201             :     }
     202             : 
     203             : 
     204             : public:
     205          63 :     ScBootstrapFixture( const OUString& rsBaseString ) : m_aBaseString( rsBaseString ) {}
     206          67 :     void createFileURL(const OUString& aFileBase, const OUString& aFileExtension, OUString& rFilePath)
     207             :     {
     208          67 :         OUString aSep("/");
     209         134 :         OUStringBuffer aBuffer( getSrcRootURL() );
     210          67 :         aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
     211          67 :         aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
     212         134 :         rFilePath = aBuffer.makeStringAndClear();
     213          67 :     }
     214             : 
     215          33 :     void createCSVPath(const OUString& aFileBase, OUString& rCSVPath)
     216             :     {
     217          33 :         OUStringBuffer aBuffer( getSrcRootPath());
     218          33 :         aBuffer.append(m_aBaseString).append(OUString("/contentCSV/"));
     219          33 :         aBuffer.append(aFileBase).append(OUString("csv"));
     220          33 :         rCSVPath = aBuffer.makeStringAndClear();
     221          33 :     }
     222             : 
     223          11 :     ScDocShellRef saveAndReload(ScDocShell* pShell, const OUString &rFilter,
     224             :     const OUString &rUserData, const OUString& rTypeName, sal_uLong nFormatType)
     225             :     {
     226             : 
     227          11 :         utl::TempFile aTempFile;
     228          11 :         aTempFile.EnableKillingFile();
     229          22 :         SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
     230          11 :         sal_uInt32 nExportFormat = 0;
     231          11 :         if (nFormatType == ODS_FORMAT_TYPE)
     232           5 :             nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
     233             :         SfxFilter* pExportFilter = new SfxFilter(
     234             :             rFilter,
     235             :             OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
     236          11 :             rUserData, OUString("private:factory/scalc*") );
     237          11 :         pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
     238          11 :         aStoreMedium.SetFilter(pExportFilter);
     239          11 :         pShell->DoSaveAs( aStoreMedium );
     240          11 :         pShell->DoClose();
     241             : 
     242             :         //std::cout << "File: " << aTempFile.GetURL() << std::endl;
     243             : 
     244          11 :         sal_uInt32 nFormat = 0;
     245          11 :         if (nFormatType == ODS_FORMAT_TYPE)
     246           5 :             nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
     247             : 
     248          22 :         return load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat );
     249             :     }
     250          11 :     ScDocShellRef saveAndReload( ScDocShell* pShell, sal_Int32 nFormat )
     251             :     {
     252          11 :         OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
     253          22 :         OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
     254          11 :         ScDocShellRef xDocSh = saveAndReload(pShell, aFilterName, OUString(), aFilterType, aFileFormats[nFormat].nFormatType);
     255             : 
     256          11 :         CPPUNIT_ASSERT(xDocSh.Is());
     257          22 :         return xDocSh;
     258             :     }
     259             : 
     260           2 :     void miscRowHeightsTest( TestParam* aTestValues, unsigned int numElems )
     261             :     {
     262           8 :         for ( unsigned int index=0; index<numElems; ++index )
     263             :         {
     264           6 :             OUString sFileName = OUString::createFromAscii( aTestValues[ index ].sTestDoc );
     265           6 :             printf("aTestValues[%u] %s\n", index, OUStringToOString( sFileName, RTL_TEXTENCODING_UTF8 ).getStr() );
     266           6 :             int nImportType =  aTestValues[ index ].nImportType;
     267           6 :             int nExportType =  aTestValues[ index ].nExportType;
     268          12 :             ScDocShellRef xShell = loadDoc( sFileName, nImportType );
     269           6 :             CPPUNIT_ASSERT(xShell.Is());
     270             : 
     271           6 :             if ( nExportType != -1 )
     272           4 :                 xShell = saveAndReload(&(*xShell), nExportType );
     273             : 
     274           6 :             CPPUNIT_ASSERT(xShell.Is());
     275             : 
     276           6 :             ScDocument* pDoc = xShell->GetDocument();
     277             : 
     278          24 :             for (int i=0; i<aTestValues[ index ].nRowData; ++i)
     279             :             {
     280          18 :                 SCROW nRow = aTestValues[ index ].pData[ i].nStartRow;
     281          18 :                 SCROW nEndRow = aTestValues[ index ].pData[ i ].nEndRow;
     282          18 :                 SCTAB nTab = aTestValues[ index ].pData[ i ].nTab;
     283          18 :                 int nExpectedHeight = aTestValues[ index ].pData[ i ].nExpectedHeight;
     284          18 :                 if ( nExpectedHeight == -1 )
     285           2 :                     nExpectedHeight =  sc::TwipsToHMM( ScGlobal::nStdRowHeight );
     286          18 :                 bool bCheckOpt = ( ( aTestValues[ index ].pData[ i ].nCheck & CHECK_OPTIMAL ) == CHECK_OPTIMAL );
     287          92 :                 for ( ; nRow <= nEndRow; ++nRow )
     288             :                 {
     289          74 :                     printf("\t checking row %" SAL_PRIdINT32 " for height %d\n", nRow, nExpectedHeight );
     290          74 :                     int nHeight = sc::TwipsToHMM( pDoc->GetRowHeight(nRow, nTab, false) );
     291          74 :                     if ( bCheckOpt )
     292             :                     {
     293           2 :                         bool bOpt = !(pDoc->GetRowFlags( nRow, nTab ) & CR_MANUALSIZE);
     294           2 :                         CPPUNIT_ASSERT_EQUAL(aTestValues[ index ].pData[ i ].bOptimal, bOpt);
     295             :                     }
     296          74 :                     CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight);
     297             :                 }
     298             :             }
     299           6 :             xShell->DoClose();
     300           6 :         }
     301           2 :     }
     302             : };
     303             : 
     304          28 : void testFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab, StringType aStringFormat = StringValue)
     305             : {
     306          28 :     csv_handler aHandler(pDoc, nTab, aStringFormat);
     307          28 :     orcus::csv_parser_config aConfig;
     308          28 :     aConfig.delimiters.push_back(',');
     309          28 :     aConfig.delimiters.push_back(';');
     310          28 :     aConfig.text_qualifier = '"';
     311          28 :     aConfig.trim_cell_value = false;
     312             : 
     313             : 
     314          56 :     std::string aContent;
     315          28 :     loadFile(aFileName, aContent);
     316          56 :     orcus::csv_parser<csv_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
     317             :     try
     318             :     {
     319          28 :         parser.parse();
     320             :     }
     321           0 :     catch (const orcus::csv_parse_error& e)
     322             :     {
     323           0 :         std::cout << "reading csv content file failed: " << e.what() << std::endl;
     324           0 :         OStringBuffer aErrorMsg("csv parser error: ");
     325           0 :         aErrorMsg.append(e.what());
     326           0 :         CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), false);
     327          28 :     }
     328          28 : }
     329             : 
     330             : //need own handler because conditional formatting strings must be generated
     331           5 : void testCondFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab)
     332             : {
     333           5 :     conditional_format_handler aHandler(pDoc, nTab);
     334           5 :     orcus::csv_parser_config aConfig;
     335           5 :     aConfig.delimiters.push_back(',');
     336           5 :     aConfig.delimiters.push_back(';');
     337           5 :     aConfig.text_qualifier = '"';
     338          10 :     std::string aContent;
     339           5 :     loadFile(aFileName, aContent);
     340          10 :     orcus::csv_parser<conditional_format_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
     341             :     try
     342             :     {
     343           5 :         parser.parse();
     344             :     }
     345           0 :     catch (const orcus::csv_parse_error& e)
     346             :     {
     347           0 :         std::cout << "reading csv content file failed: " << e.what() << std::endl;
     348           0 :         OStringBuffer aErrorMsg("csv parser error: ");
     349           0 :         aErrorMsg.append(e.what());
     350           0 :         CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), false);
     351           5 :     }
     352             : 
     353           5 : }
     354             : 
     355             : #define ASSERT_DOUBLES_EQUAL( expected, result )    \
     356             :     CPPUNIT_ASSERT_DOUBLES_EQUAL( (expected), (result), 1e-14 )
     357             : 
     358             : #define ASSERT_DOUBLES_EQUAL_MESSAGE( message, expected, result )   \
     359             :     CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( (message), (expected), (result), 1e-14 )
     360             : 
     361             : #endif
     362             : 
     363             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10