update credits
[LibreOffice.git] / sc / qa / unit / helper / qahelper.hxx
blob4a182655dbcbb47f1834c0bd6f6ff777f918e576
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 */
10 #ifndef SC_QA_HELPER_HXX
11 #define SC_QA_HELPER_HXX
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>
22 #include <comphelper/documentconstants.hxx>
24 #include <osl/detail/android-bootstrap.h>
26 #include <unotools/tempfile.hxx>
27 #include <comphelper/storagehelper.hxx>
28 #include <sfx2/docfilt.hxx>
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)
37 #define ODS 0
38 #define XLS 1
39 #define XLSX 2
40 #define CSV 3
41 #define HTML 4
42 #define LOTUS123 5
44 bool testEqualsWithTolerance( long nVal1, long nVal2, long nTol )
46 return ( labs( nVal1 - nVal2 ) <= nTol );
49 struct FileFormat {
50 const char* pName; const char* pFilterName; const char* pTypeName; unsigned int nFormatType;
53 #define CHECK_OPTIMAL 0x1
55 // data format for row height tests
56 struct TestParam
58 struct RowData
60 SCROW nStartRow;
61 SCROW nEndRow;
62 SCTAB nTab;
63 int nExpectedHeight; // -1 for default height
64 int nCheck; // currently only CHECK_OPTIMAL ( we could add CHECK_MANUAL etc.)
65 bool bOptimal;
67 const char* sTestDoc;
68 int nImportType;
69 int nExportType; // -1 for import test, otherwise this is an export test
70 int nRowData;
71 RowData* pData;
74 FileFormat aFileFormats[] = {
75 { "ods" , "calc8", "", ODS_FORMAT_TYPE },
76 { "xls" , "MS Excel 97", "calc_MS_EXCEL_97", XLS_FORMAT_TYPE },
77 { "xlsx", "Calc MS Excel 2007 XML" , "MS Excel 2007 XML", XLSX_FORMAT_TYPE },
78 { "csv" , "Text - txt - csv (StarCalc)", "generic_Text", CSV_FORMAT_TYPE },
79 { "html" , "calc_HTML_WebQuery", "generic_HTML", HTML_FORMAT_TYPE },
80 { "123" , "Lotus", "calc_Lotus", LOTUS123_FORMAT_TYPE },
83 // Why is this here and not in osl, and using the already existing file
84 // handling APIs? Do we really want to add arbitrary new file handling
85 // wrappers here and there (and then having to handle the Android (and
86 // eventually perhaps iOS) special cases here, too)? Please move this to osl,
87 // it sure looks gemerally useful. Or am I missing something?
89 void loadFile(const OUString& aFileName, std::string& aContent)
91 OString aOFileName = OUStringToOString(aFileName, RTL_TEXTENCODING_UTF8);
93 #ifdef ANDROID
94 size_t size;
95 if (strncmp(aOFileName.getStr(), "/assets/", sizeof("/assets/")-1) == 0) {
96 const char *contents = (const char *) lo_apkentry(aOFileName.getStr(), &size);
97 if (contents != 0) {
98 aContent = std::string(contents, size);
99 return;
102 #endif
104 std::ifstream aFile(aOFileName.getStr());
106 OStringBuffer aErrorMsg("Could not open csv file: ");
107 aErrorMsg.append(aOFileName);
108 CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), aFile);
109 std::ostringstream aOStream;
110 aOStream << aFile.rdbuf();
111 aFile.close();
112 aContent = aOStream.str();
115 class ScBootstrapFixture : public test::BootstrapFixture
117 protected:
118 OUString m_aBaseString;
119 ScDocShellRef load( bool bReadWrite,
120 const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
121 const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID, sal_uIntPtr nFilterVersion = SOFFICE_FILEFORMAT_CURRENT, const OUString* pPassword = NULL )
123 SfxFilter* pFilter = new SfxFilter(
124 rFilter,
125 OUString(), nFilterFlags, nClipboardID, rTypeName, 0, OUString(),
126 rUserData, OUString("private:factory/scalc*"));
127 pFilter->SetVersion(nFilterVersion);
129 ScDocShellRef xDocShRef = new ScDocShell;
130 xDocShRef->GetDocument()->EnableUserInteraction(false);
131 SfxMedium* pSrcMed = new SfxMedium(rURL, bReadWrite ? STREAM_STD_READWRITE : STREAM_STD_READ );
132 pSrcMed->SetFilter(pFilter);
133 pSrcMed->UseInteractionHandler(false);
134 if (pPassword)
136 SfxItemSet* pSet = pSrcMed->GetItemSet();
137 pSet->Put(SfxStringItem(SID_PASSWORD, *pPassword));
139 printf("about to load %s\n", OUStringToOString( rURL, RTL_TEXTENCODING_UTF8 ).getStr() );
140 if (!xDocShRef->DoLoad(pSrcMed))
142 xDocShRef->DoClose();
143 // load failed.
144 xDocShRef.Clear();
147 return xDocShRef;
150 ScDocShellRef load(
151 const OUString& rURL, const OUString& rFilter, const OUString &rUserData,
152 const OUString& rTypeName, unsigned int nFilterFlags, unsigned int nClipboardID, sal_uIntPtr nFilterVersion = SOFFICE_FILEFORMAT_CURRENT, const OUString* pPassword = NULL )
154 return load( false, rURL, rFilter, rUserData, rTypeName, nFilterFlags, nClipboardID, nFilterVersion, pPassword );
157 ScDocShellRef loadDoc(const OUString& rFileName, sal_Int32 nFormat, bool bReadWrite = false )
159 OUString aFileExtension(aFileFormats[nFormat].pName, strlen(aFileFormats[nFormat].pName), RTL_TEXTENCODING_UTF8 );
160 OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
161 OUString aFileName;
162 createFileURL( rFileName, aFileExtension, aFileName );
163 OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
164 unsigned int nFormatType = aFileFormats[nFormat].nFormatType;
165 unsigned int nClipboardId = nFormatType ? SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS : 0;
167 return load(bReadWrite, aFileName, aFilterName, OUString(), aFilterType, nFormatType, nClipboardId, nFormatType);
171 public:
172 ScBootstrapFixture( const OUString& rsBaseString ) : m_aBaseString( rsBaseString ) {}
173 void createFileURL(const OUString& aFileBase, const OUString& aFileExtension, OUString& rFilePath)
175 OUString aSep("/");
176 OUStringBuffer aBuffer( getSrcRootURL() );
177 aBuffer.append(m_aBaseString).append(aSep).append(aFileExtension);
178 aBuffer.append(aSep).append(aFileBase).append(aFileExtension);
179 rFilePath = aBuffer.makeStringAndClear();
182 void createCSVPath(const OUString& aFileBase, OUString& rCSVPath)
184 OUStringBuffer aBuffer( getSrcRootPath());
185 aBuffer.append(m_aBaseString).append(OUString("/contentCSV/"));
186 aBuffer.append(aFileBase).append(OUString("csv"));
187 rCSVPath = aBuffer.makeStringAndClear();
190 ScDocShellRef saveAndReload(ScDocShell* pShell, const OUString &rFilter,
191 const OUString &rUserData, const OUString& rTypeName, sal_uLong nFormatType)
194 utl::TempFile aTempFile;
195 aTempFile.EnableKillingFile();
196 SfxMedium aStoreMedium( aTempFile.GetURL(), STREAM_STD_WRITE );
197 sal_uInt32 nExportFormat = 0;
198 if (nFormatType == ODS_FORMAT_TYPE)
199 nExportFormat = SFX_FILTER_EXPORT | SFX_FILTER_USESOPTIONS;
200 SfxFilter* pExportFilter = new SfxFilter(
201 rFilter,
202 OUString(), nFormatType, nExportFormat, rTypeName, 0, OUString(),
203 rUserData, OUString("private:factory/scalc*") );
204 pExportFilter->SetVersion(SOFFICE_FILEFORMAT_CURRENT);
205 aStoreMedium.SetFilter(pExportFilter);
206 pShell->DoSaveAs( aStoreMedium );
207 pShell->DoClose();
209 //std::cout << "File: " << aTempFile.GetURL() << std::endl;
211 sal_uInt32 nFormat = 0;
212 if (nFormatType == ODS_FORMAT_TYPE)
213 nFormat = SFX_FILTER_IMPORT | SFX_FILTER_USESOPTIONS;
215 return load(aTempFile.GetURL(), rFilter, rUserData, rTypeName, nFormatType, nFormat );
217 ScDocShellRef saveAndReload( ScDocShell* pShell, sal_Int32 nFormat )
219 OUString aFilterName(aFileFormats[nFormat].pFilterName, strlen(aFileFormats[nFormat].pFilterName), RTL_TEXTENCODING_UTF8) ;
220 OUString aFilterType(aFileFormats[nFormat].pTypeName, strlen(aFileFormats[nFormat].pTypeName), RTL_TEXTENCODING_UTF8);
221 ScDocShellRef xDocSh = saveAndReload(pShell, aFilterName, OUString(), aFilterType, aFileFormats[nFormat].nFormatType);
223 CPPUNIT_ASSERT(xDocSh.Is());
224 return xDocSh;
227 void miscRowHeightsTest( TestParam* aTestValues, unsigned int numElems )
229 for ( unsigned int index=0; index<numElems; ++index )
231 OUString sFileName = OUString::createFromAscii( aTestValues[ index ].sTestDoc );
232 printf("aTestValues[%u] %s\n", index, OUStringToOString( sFileName, RTL_TEXTENCODING_UTF8 ).getStr() );
233 int nImportType = aTestValues[ index ].nImportType;
234 int nExportType = aTestValues[ index ].nExportType;
235 ScDocShellRef xShell = loadDoc( sFileName, nImportType );
236 CPPUNIT_ASSERT(xShell.Is());
238 if ( nExportType != -1 )
239 xShell = saveAndReload(&(*xShell), nExportType );
241 CPPUNIT_ASSERT(xShell.Is());
243 ScDocument* pDoc = xShell->GetDocument();
245 for (int i=0; i<aTestValues[ index ].nRowData; ++i)
247 SCROW nRow = aTestValues[ index ].pData[ i].nStartRow;
248 SCROW nEndRow = aTestValues[ index ].pData[ i ].nEndRow;
249 SCTAB nTab = aTestValues[ index ].pData[ i ].nTab;
250 int nExpectedHeight = aTestValues[ index ].pData[ i ].nExpectedHeight;
251 if ( nExpectedHeight == -1 )
252 nExpectedHeight = sc::TwipsToHMM( ScGlobal::nStdRowHeight );
253 bool bCheckOpt = ( ( aTestValues[ index ].pData[ i ].nCheck & CHECK_OPTIMAL ) == CHECK_OPTIMAL );
254 for ( ; nRow <= nEndRow; ++nRow )
256 printf("\t checking row %" SAL_PRIdINT32 " for height %d\n", nRow, nExpectedHeight );
257 int nHeight = sc::TwipsToHMM( pDoc->GetRowHeight(nRow, nTab, false) );
258 if ( bCheckOpt )
260 bool bOpt = !(pDoc->GetRowFlags( nRow, nTab ) & CR_MANUALSIZE);
261 CPPUNIT_ASSERT_EQUAL(aTestValues[ index ].pData[ i ].bOptimal, bOpt);
263 CPPUNIT_ASSERT_EQUAL(nExpectedHeight, nHeight);
266 xShell->DoClose();
271 void testFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab, StringType aStringFormat = StringValue)
273 csv_handler aHandler(pDoc, nTab, aStringFormat);
274 orcus::csv_parser_config aConfig;
275 aConfig.delimiters.push_back(',');
276 aConfig.delimiters.push_back(';');
277 aConfig.text_qualifier = '"';
278 aConfig.trim_cell_value = false;
281 std::string aContent;
282 loadFile(aFileName, aContent);
283 orcus::csv_parser<csv_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
286 parser.parse();
288 catch (const orcus::csv_parse_error& e)
290 std::cout << "reading csv content file failed: " << e.what() << std::endl;
291 OStringBuffer aErrorMsg("csv parser error: ");
292 aErrorMsg.append(e.what());
293 CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), false);
297 //need own handler because conditional formatting strings must be generated
298 void testCondFile(OUString& aFileName, ScDocument* pDoc, SCTAB nTab)
300 conditional_format_handler aHandler(pDoc, nTab);
301 orcus::csv_parser_config aConfig;
302 aConfig.delimiters.push_back(',');
303 aConfig.delimiters.push_back(';');
304 aConfig.text_qualifier = '"';
305 std::string aContent;
306 loadFile(aFileName, aContent);
307 orcus::csv_parser<conditional_format_handler> parser ( &aContent[0], aContent.size() , aHandler, aConfig);
310 parser.parse();
312 catch (const orcus::csv_parse_error& e)
314 std::cout << "reading csv content file failed: " << e.what() << std::endl;
315 OStringBuffer aErrorMsg("csv parser error: ");
316 aErrorMsg.append(e.what());
317 CPPUNIT_ASSERT_MESSAGE(aErrorMsg.getStr(), false);
322 #define ASSERT_DOUBLES_EQUAL( expected, result ) \
323 CPPUNIT_ASSERT_DOUBLES_EQUAL( (expected), (result), 1e-14 )
325 #define ASSERT_DOUBLES_EQUAL_MESSAGE( message, expected, result ) \
326 CPPUNIT_ASSERT_DOUBLES_EQUAL_MESSAGE( (message), (expected), (result), 1e-14 )
328 #endif
330 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */