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 INCLUDED_SC_QA_UNIT_HELPER_SHARED_TEST_IMPL_HXX
11 #define INCLUDED_SC_QA_UNIT_HELPER_SHARED_TEST_IMPL_HXX
12 
13 #include <memory>
14 #include <colorscale.hxx>
15 #include <conditio.hxx>
16 #include <document.hxx>
17 #include <formulacell.hxx>
18 #include "qahelper.hxx"
19 #include <formula/errorcodes.hxx>
20 
21 struct FindCondFormatByEnclosingRange
22 {
FindCondFormatByEnclosingRangeFindCondFormatByEnclosingRange23     explicit FindCondFormatByEnclosingRange(const ScRange& rRange):
24         mrRange(rRange) {}
25 
operator ()FindCondFormatByEnclosingRange26     bool operator()(const std::unique_ptr<ScConditionalFormat>& pFormat)
27     {
28         if (pFormat->GetRange().Combine() == mrRange)
29             return true;
30 
31         return false;
32     }
33 
34 private:
35     const ScRange& mrRange;
36 };
37 
38 struct DataBarData
39 {
40     ScRange aRange;
41     ScColorScaleEntryType eLowerLimitType;
42     ScColorScaleEntryType eUpperLimitType;
43     databar::ScAxisPosition eAxisPosition;
44 };
45 
46 DataBarData const aData[] = {
47     { ScRange(1,2,0,1,5,0), COLORSCALE_AUTO, COLORSCALE_AUTO, databar::AUTOMATIC },
48     { ScRange(3,2,0,3,5,0), COLORSCALE_MIN, COLORSCALE_MAX, databar::AUTOMATIC },
49     { ScRange(5,2,0,5,5,0), COLORSCALE_PERCENTILE, COLORSCALE_PERCENT, databar::AUTOMATIC },
50     { ScRange(7,2,0,7,5,0), COLORSCALE_VALUE, COLORSCALE_FORMULA, databar::AUTOMATIC },
51     { ScRange(1,9,0,1,12,0), COLORSCALE_AUTO, COLORSCALE_AUTO, databar::MIDDLE }
52 };
53 
testDataBar_Impl(const ScDocument & rDoc)54 void testDataBar_Impl(const ScDocument& rDoc)
55 {
56     ScConditionalFormatList* pList = rDoc.GetCondFormList(0);
57     CPPUNIT_ASSERT(pList);
58 
59     for(size_t i = 0; i < SAL_N_ELEMENTS(aData); ++i)
60     {
61         ScConditionalFormatList::const_iterator itr = std::find_if(pList->begin(),
62                 pList->end(), FindCondFormatByEnclosingRange(aData[i].aRange));
63         CPPUNIT_ASSERT(itr != pList->end());
64         CPPUNIT_ASSERT_EQUAL(size_t(1), (*itr)->size());
65 
66         const ScFormatEntry* pFormatEntry = (*itr)->GetEntry(0);
67         CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Databar, pFormatEntry->GetType());
68         const ScDataBarFormat* pDataBar = static_cast<const ScDataBarFormat*>(pFormatEntry);
69         CPPUNIT_ASSERT(pDataBar);
70         const ScDataBarFormatData* pDataBarData = pDataBar->GetDataBarData();
71         CPPUNIT_ASSERT_EQUAL(aData[i].eLowerLimitType, pDataBarData->mpLowerLimit->GetType());
72         CPPUNIT_ASSERT_EQUAL(aData[i].eUpperLimitType, pDataBarData->mpUpperLimit->GetType());
73 
74         CPPUNIT_ASSERT_EQUAL(aData[i].eAxisPosition, pDataBarData->meAxisPosition);
75     }
76 }
77 
78 struct ColorScale2EntryData
79 {
80     ScRange aRange;
81     ScColorScaleEntryType eLowerType;
82     ScColorScaleEntryType eUpperType;
83 };
84 
85 ColorScale2EntryData const aData2Entry[] = {
86     { ScRange(1,2,0,1,5,0), COLORSCALE_MIN, COLORSCALE_MAX },
87     { ScRange(3,2,0,3,5,0), COLORSCALE_PERCENTILE, COLORSCALE_PERCENT },
88     { ScRange(5,2,0,5,5,0), COLORSCALE_VALUE, COLORSCALE_FORMULA }
89 };
90 
testColorScale2Entry_Impl(const ScDocument & rDoc)91 void testColorScale2Entry_Impl(const ScDocument& rDoc)
92 {
93     const ScConditionalFormatList* pList = rDoc.GetCondFormList(0);
94     CPPUNIT_ASSERT(pList);
95 
96     for(size_t i = 0; i < SAL_N_ELEMENTS(aData2Entry); ++i)
97     {
98         ScConditionalFormatList::const_iterator itr = std::find_if(pList->begin(),
99                             pList->end(), FindCondFormatByEnclosingRange(aData2Entry[i].aRange));
100         CPPUNIT_ASSERT(itr != pList->end());
101         CPPUNIT_ASSERT_EQUAL(size_t(1), (*itr)->size());
102 
103         const ScFormatEntry* pFormatEntry = (*itr)->GetEntry(0);
104         CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Colorscale, pFormatEntry->GetType());
105         const ScColorScaleFormat* pColFormat = static_cast<const ScColorScaleFormat*>(pFormatEntry);
106         CPPUNIT_ASSERT_EQUAL(size_t(2), pColFormat->size());
107 
108         ScColorScaleEntries::const_iterator format_itr = pColFormat->begin();
109         CPPUNIT_ASSERT_EQUAL(aData2Entry[i].eLowerType, (*format_itr)->GetType());
110         ++format_itr;
111         CPPUNIT_ASSERT(format_itr != pColFormat->end());
112         CPPUNIT_ASSERT_EQUAL(aData2Entry[i].eUpperType, (*format_itr)->GetType());
113     }
114 }
115 
116 struct ColorScale3EntryData
117 {
118     ScRange aRange;
119     ScColorScaleEntryType eLowerType;
120     ScColorScaleEntryType eMiddleType;
121     ScColorScaleEntryType eUpperType;
122 };
123 
124 ColorScale3EntryData const aData3Entry[] = {
125     { ScRange(1,1,1,1,6,1), COLORSCALE_MIN, COLORSCALE_PERCENTILE, COLORSCALE_MAX },
126     { ScRange(3,1,1,3,6,1), COLORSCALE_PERCENTILE, COLORSCALE_VALUE, COLORSCALE_PERCENT },
127     { ScRange(5,1,1,5,6,1), COLORSCALE_VALUE, COLORSCALE_VALUE, COLORSCALE_FORMULA }
128 };
129 
testColorScale3Entry_Impl(const ScDocument & rDoc)130 void testColorScale3Entry_Impl(const ScDocument& rDoc)
131 {
132     ScConditionalFormatList* pList = rDoc.GetCondFormList(1);
133     CPPUNIT_ASSERT(pList);
134 
135     for(size_t i = 0; i < SAL_N_ELEMENTS(aData3Entry); ++i)
136     {
137         ScConditionalFormatList::const_iterator itr = std::find_if(pList->begin(),
138                             pList->end(), FindCondFormatByEnclosingRange(aData3Entry[i].aRange));
139         CPPUNIT_ASSERT(itr != pList->end());
140         CPPUNIT_ASSERT_EQUAL(size_t(1), (*itr)->size());
141 
142         const ScFormatEntry* pFormatEntry = (*itr)->GetEntry(0);
143         CPPUNIT_ASSERT_EQUAL(ScFormatEntry::Type::Colorscale, pFormatEntry->GetType());
144         const ScColorScaleFormat* pColFormat = static_cast<const ScColorScaleFormat*>(pFormatEntry);
145         CPPUNIT_ASSERT_EQUAL(size_t(3), pColFormat->size());
146 
147         ScColorScaleEntries::const_iterator format_itr = pColFormat->begin();
148         CPPUNIT_ASSERT_EQUAL(aData3Entry[i].eLowerType, (*format_itr)->GetType());
149         ++format_itr;
150         CPPUNIT_ASSERT(format_itr != pColFormat->end());
151         CPPUNIT_ASSERT_EQUAL(aData3Entry[i].eMiddleType, (*format_itr)->GetType());
152         ++format_itr;
153         CPPUNIT_ASSERT(format_itr != pColFormat->end());
154         CPPUNIT_ASSERT_EQUAL(aData3Entry[i].eUpperType, (*format_itr)->GetType());
155     }
156 }
157 
testFunctionsExcel2010_Impl(ScDocument & rDoc)158 void testFunctionsExcel2010_Impl( ScDocument& rDoc )
159 {
160     // Original test case document is functions-excel-2010.xlsx
161     // Which test rows to evaluate, 1-based as in UI to ease maintenance.
162     static struct
163     {
164         SCROW nRow;
165         bool  bEvaluate;
166     } const aTests[] = {
167         {  2, false },  // name=[ AGGREGATE ], result=0, expected=1
168         {  3, true  },
169         {  4, true  },
170         {  5, true  },
171         {  6, true  },
172         {  7, true  },
173         {  8, true  },
174         {  9, true  },
175         { 10, true  },
176         { 11, true  },
177         { 12, true  },
178         { 13, true  },
179         { 14, true  },
180         { 15, true  },
181         { 16, true  },
182         { 17, true  },
183         { 18, true  },
184         { 19, true  },
185         { 20, true  },
186         { 21, true  },
187         { 22, true  },
188         { 23, true  },
189         { 24, true  },
190         { 25, true  },
191         { 26, true  },
192         { 27, true  },
193         { 28, true  },
194         { 29, true  },
195         { 30, true  },
196         { 31, true  },
197         { 32, true  },
198         { 33, true  },
199         { 34, true  },
200         { 35, true  },
201         { 36, true  },
202         { 37, true  },
203         { 38, true  },
204         { 39, true  },
205         { 40, true  },
206         { 41, true  },
207         { 42, true  },
208         { 43, true  },
209         { 44, true  },
210         { 45, false },  // name=[ NETWORKDAYS.INTL ], result=18, expected=19
211         { 46, true  },
212         { 47, true  },
213         { 48, true  },
214         { 49, true  },
215         { 50, true  },
216         { 51, true  },
217         { 52, true  },
218         { 53, true  },
219         { 54, true  },
220         { 55, true  },
221         { 56, true  },
222         { 57, true  },
223         { 58, true  },
224         { 59, true  },
225         { 60, true  },
226         { 61, true  },
227         { 62, true  },
228         { 63, true  },
229         { 64, true  },
230         { 65, true  },
231         { 66, true  },
232         { 67, true  },
233         { 68, true  },
234         { 69, true  },
235         { 70, true  },
236         { 71, true  },
237         { 72, true  },
238         { 73, true  },
239         { 74, true  },
240         { 75, true  },
241         { 76, true  },
242         { 77, true  },
243         { 78, true  },
244         { 79, false },  // name=[ WORKDAY.INTL ], result=41755 , expected=41754
245         { 80, true  }
246     };
247 
248     for (size_t i=0; i < SAL_N_ELEMENTS(aTests); ++i)
249     {
250         if (aTests[i].bEvaluate)
251         {
252             // Column 0 is description, 1 is formula, 2 is Excel result, 3 is
253             // comparison.
254             SCROW nRow = aTests[i].nRow - 1;    // 0-based
255 
256             OString aStr = OString::number( aTests[i].nRow) +
257                 ", function name=[ " +
258                 OUStringToOString( rDoc.GetString( ScAddress( 0, nRow, 0)), RTL_TEXTENCODING_UTF8 ) +
259                 " ], result=" +
260                 OString::number( rDoc.GetValue( ScAddress( 1, nRow, 0)) ) +
261                 ", expected=" +
262                 OString::number( rDoc.GetValue( ScAddress( 2, nRow, 0)) );
263 
264             ScFormulaCell* pFC = rDoc.GetFormulaCell( ScAddress( 1, nRow, 0) );
265             if ( pFC && pFC->GetErrCode() != FormulaError::NONE )
266                 aStr += ", error code =" + OString::number( static_cast<int>(pFC->GetErrCode()) );
267 
268             CPPUNIT_ASSERT_MESSAGE( OString( "Expected a formula cell without error at row " +
269                     aStr ).getStr(), isFormulaWithoutError( rDoc, ScAddress( 1, nRow, 0)));
270             CPPUNIT_ASSERT_MESSAGE( OString( "Expected a TRUE value at row " +
271                     aStr ).getStr(), 0 != rDoc.GetValue( ScAddress( 3, nRow, 0)));
272 
273         }
274     }
275 }
276 
testCeilingFloor_Impl(ScDocument & rDoc)277 void testCeilingFloor_Impl( ScDocument& rDoc )
278 {
279     // Original test case document is ceiling-floor.xlsx
280     // Sheet1.K1 has =AND(K3:K81) to evaluate all results.
281     const char pORef[] = "Sheet1.K1";
282     OUString aRef(pORef);
283     ScAddress aPos;
284     aPos.Parse(aRef, &rDoc);
285     ASSERT_FORMULA_EQUAL(rDoc, aPos, "AND(K3:K81)", "Wrong formula.");
286     CPPUNIT_ASSERT_MESSAGE( OString( pORef + OStringLiteral(" result is error.")).getStr(),
287             isFormulaWithoutError( rDoc, aPos));
288     CPPUNIT_ASSERT_EQUAL(1.0, rDoc.GetValue(aPos));
289 }
290 
291 #endif
292 
293 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
294