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