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 : #ifdef WNT
11 : # undef ERROR
12 : #endif
13 :
14 : #include <sal/types.h>
15 : #include <cppunit/TestAssert.h>
16 : #include <cppunit/TestFixture.h>
17 : #include <cppunit/extensions/HelperMacros.h>
18 : #include <cppunit/plugin/TestPlugIn.h>
19 :
20 : #include <sal/config.h>
21 : #include <osl/file.hxx>
22 : #include <osl/process.h>
23 : #include <rtl/ustrbuf.hxx>
24 :
25 : #include <cppuhelper/bootstrap.hxx>
26 : #include <comphelper/processfactory.hxx>
27 :
28 : #include <com/sun/star/sheet/DataPilotFieldOrientation.hpp>
29 : #include <com/sun/star/sheet/GeneralFunction.hpp>
30 : #include <com/sun/star/lang/XComponent.hpp>
31 :
32 : #include <i18nlangtag/lang.h>
33 :
34 : #include "svl/zforlist.hxx"
35 : #include "svl/zformat.hxx"
36 :
37 : #define DEBUG_UNIT_TEST 0
38 :
39 : #if DEBUG_UNIT_TEST
40 : #include <iostream>
41 : #endif
42 :
43 : using namespace ::com::sun::star;
44 :
45 : #if DEBUG_UNIT_TEST
46 : using ::std::cout;
47 : using ::std::endl;
48 : #endif
49 :
50 : namespace {
51 :
52 : #if DEBUG_UNIT_TEST
53 : ::std::ostream& operator<< (::std::ostream& os, const OUString& str)
54 : {
55 : return os << OUStringToOString(str, RTL_TEXTENCODING_UTF8).getStr();
56 : }
57 : #endif
58 :
59 : class Test : public CppUnit::TestFixture {
60 : public:
61 : Test();
62 : ~Test();
63 :
64 : virtual void setUp();
65 : virtual void tearDown();
66 :
67 : void testNumberFormat();
68 : void testFdo60915();
69 : void testI116701();
70 :
71 2 : CPPUNIT_TEST_SUITE(Test);
72 1 : CPPUNIT_TEST(testNumberFormat);
73 1 : CPPUNIT_TEST(testFdo60915);
74 1 : CPPUNIT_TEST(testI116701);
75 2 : CPPUNIT_TEST_SUITE_END();
76 :
77 : private:
78 : uno::Reference< uno::XComponentContext > m_xContext;
79 : void checkPreviewString(SvNumberFormatter& aFormatter,
80 : const OUString& sCode,
81 : double fPreviewNumber,
82 : LanguageType eLang,
83 : OUString& sExpected);
84 : };
85 :
86 3 : Test::Test()
87 : {
88 3 : m_xContext = cppu::defaultBootstrap_InitialComponentContext();
89 :
90 3 : uno::Reference<lang::XMultiComponentFactory> xFactory(m_xContext->getServiceManager());
91 6 : uno::Reference<lang::XMultiServiceFactory> xSM(xFactory, uno::UNO_QUERY_THROW);
92 :
93 : //Without this we're crashing because callees are using
94 : //getProcessServiceFactory. In general those should be removed in favour
95 : //of retaining references to the root ServiceFactory as its passed around
96 6 : comphelper::setProcessServiceFactory(xSM);
97 3 : }
98 :
99 3 : void Test::setUp()
100 : {
101 3 : }
102 :
103 3 : void Test::tearDown()
104 : {
105 3 : }
106 :
107 9 : Test::~Test()
108 : {
109 3 : uno::Reference< lang::XComponent >(m_xContext, uno::UNO_QUERY_THROW)->dispose();
110 6 : }
111 :
112 1 : void Test::testNumberFormat()
113 : {
114 1 : LanguageType eLang = LANGUAGE_ENGLISH_US;
115 :
116 : const char* pNumber[] = {
117 : "General",
118 : "0",
119 : "0.00",
120 : "#,##0",
121 : "#,##0.00",
122 : "#,###.00",
123 : 0
124 1 : };
125 :
126 : const char* pScientific[] = {
127 : "0.00E+000",
128 : "0.00E+00",
129 : 0
130 1 : };
131 :
132 : const char* pPercent[] = {
133 : "0%",
134 : "0.00%",
135 : 0
136 1 : };
137 :
138 : const char* pFraction[] = {
139 : "# \?/\?",
140 : "# \?\?/\?\?",
141 : #if 0
142 : // TODO: Followings aren't in range of NF_FRACTION_START and NF_FRACTION_END
143 : // see enum NfIndexTableOffset in svl/inc/svl/zforlist.hxx
144 : "# \?/4",
145 : "# \?\?/100",
146 : #endif
147 : 0
148 1 : };
149 :
150 : #if 0 // TODO: Find out why on some systems the last two currency format codes differ.
151 : const char* pCurrency[] = {
152 : "$#,##0;[RED]-$#,##0",
153 : "$#,##0.00;[RED]-$#,##0.00",
154 : "#,##0.00 CCC",
155 : "$#,##0.--;[RED]-$#,##0.--",
156 : "$#,##0;-$#,##0",
157 : "$#,##0;-$#,##0",
158 : 0
159 : };
160 : #endif
161 :
162 : #if 0 // TODO: This currently fails
163 : const char* pDate[] = {
164 : "MM/DD/YY",
165 : "MM/DD/YYYY",
166 : "MMM D, YY",
167 : "MMM D, YYYY",
168 : "D. MMM. YYYY",
169 : "MMMM D, YYYY",
170 : "D. MMMM YYYY",
171 : "NN, MMM D, YY",
172 : "NN DD/MMM YY",
173 : "NN, MMMM D, YYYY",
174 : "NNNNMMMM D, YYYY",
175 : "MM-DD",
176 : "YY-MM-DD",
177 : "YYYY-MM-DD",
178 : "MM/YY",
179 : "MMM DD",
180 : "MMMM",
181 : "QQ YY",
182 : "WW",
183 : "MM/DD/YY",
184 : "WW",
185 : 0
186 : };
187 : #endif
188 :
189 : const char* pTime[] = {
190 : "HH:MM",
191 : "HH:MM:SS",
192 : "HH:MM AM/PM",
193 : "HH:MM:SS AM/PM",
194 : "[HH]:MM:SS",
195 : "MM:SS.00",
196 : "[HH]:MM:SS.00",
197 : 0
198 1 : };
199 :
200 : #if 0 // TODO: This currently fails
201 : const char* pDateTime[] = {
202 : "MM/DD/YY HH:MM AM/PM",
203 : "MM/DD/YY HH:MM AM/PM",
204 : 0
205 : };
206 : #endif
207 :
208 : const char* pBoolean[] = {
209 : "BOOLEAN",
210 : 0
211 1 : };
212 :
213 : const char* pText[] = {
214 : "@",
215 : 0
216 1 : };
217 :
218 : struct {
219 : NfIndexTableOffset eStart;
220 : NfIndexTableOffset eEnd;
221 : size_t nSize;
222 : const char** pCodes;
223 : } aTests[] = {
224 : { NF_NUMBER_START, NF_NUMBER_END, 6, pNumber },
225 : { NF_SCIENTIFIC_START, NF_SCIENTIFIC_END, 2, pScientific },
226 : { NF_PERCENT_START, NF_PERCENT_END, 2, pPercent },
227 : { NF_FRACTION_START, NF_FRACTION_END, 2, pFraction },
228 : #if 0 // TODO: Find out why on some systems the last two currency format codes differ.
229 : { NF_CURRENCY_START, NF_CURRENCY_END, 6, pCurrency },
230 : #endif
231 : #if 0 // TODO: This currently fails
232 : { NF_DATE_START, NF_DATE_END, 21, pDate },
233 : #endif
234 : { NF_TIME_START, NF_TIME_END, 7, pTime },
235 : #if 0 // TODO: This currently fails
236 : { NF_DATETIME_START, NF_DATETIME_END, 2, pDateTime },
237 : #endif
238 : { NF_BOOLEAN, NF_BOOLEAN, 1, pBoolean },
239 : { NF_TEXT, NF_TEXT, 1, pText }
240 1 : };
241 :
242 1 : SvNumberFormatter aFormatter(m_xContext, eLang);
243 :
244 8 : for (size_t i = 0; i < SAL_N_ELEMENTS(aTests); ++i)
245 : {
246 7 : size_t nStart = aTests[i].eStart;
247 7 : size_t nEnd = aTests[i].eEnd;
248 :
249 14 : CPPUNIT_ASSERT_MESSAGE("Unexpected number of formats for this category.",
250 7 : (nEnd - nStart + 1) == aTests[i].nSize);
251 :
252 28 : for (size_t j = nStart; j <= nEnd; ++j)
253 : {
254 : sal_uInt32 nIndex =
255 21 : aFormatter.GetFormatIndex(static_cast<NfIndexTableOffset>(j));
256 21 : const SvNumberformat* p = aFormatter.GetEntry(nIndex);
257 :
258 21 : CPPUNIT_ASSERT_MESSAGE("Number format entry is expected, but doesn't exist.", p);
259 21 : OUString aCode = p->GetFormatstring();
260 21 : bool bEqual = aCode.equalsAscii(aTests[i].pCodes[j-nStart]);
261 21 : CPPUNIT_ASSERT_MESSAGE("Unexpected number format code.", bEqual);
262 21 : }
263 : }
264 :
265 : sal_Int32 nPos;
266 1 : short nType = NUMBERFORMAT_DEFINED;
267 : sal_uInt32 nKey;
268 2 : OUString aCode;
269 : // Thai date format (implicit locale).
270 1 : aCode = "[$-1070000]d/mm/yyyy;@";
271 1 : if (!aFormatter.PutEntry(aCode, nPos, nType, nKey))
272 : {
273 0 : CPPUNIT_ASSERT_MESSAGE("failed to insert format code '[$-1070000]d/mm/yyyy;@'", false);
274 : }
275 :
276 : // Thai date format (explicit locale)
277 1 : aCode = "[$-107041E]d/mm/yyyy;@";
278 1 : if (!aFormatter.PutEntry(aCode, nPos, nType, nKey))
279 : {
280 0 : CPPUNIT_ASSERT_MESSAGE("failed to insert format code '[$-107041E]d/mm/yyyy;@'", false);
281 : }
282 :
283 : // Thai date format (using buddhist calendar type).
284 1 : aCode = "[~buddhist]D MMMM YYYY";
285 1 : if (!aFormatter.PutEntry(aCode, nPos, nType, nKey))
286 : {
287 0 : CPPUNIT_ASSERT_MESSAGE("failed to insert format code '[~buddhist]D MMMM YYYY'", false);
288 1 : }
289 1 : }
290 :
291 6 : void Test::checkPreviewString(SvNumberFormatter& aFormatter,
292 : const OUString& sCode,
293 : double fPreviewNumber,
294 : LanguageType eLang,
295 : OUString& sExpected)
296 : {
297 6 : OUString sStr;
298 6 : Color* pColor = 0;
299 6 : Color** ppColor = &pColor;
300 6 : if (!aFormatter.GetPreviewString(sCode, fPreviewNumber, sStr, ppColor, eLang))
301 0 : CPPUNIT_FAIL("GetPreviewString() failed");
302 6 : CPPUNIT_ASSERT_EQUAL(sExpected, sStr);
303 6 : }
304 :
305 1 : void Test::testFdo60915()
306 : {
307 1 : LanguageType eLang = LANGUAGE_THAI;
308 2 : OUString sCode, sExpected;
309 1 : double fPreviewNumber = 36486; // equals 1999-11-22 (2542 B.E.)
310 2 : SvNumberFormatter aFormatter(m_xContext, eLang);
311 : {
312 1 : sCode = "[~buddhist]D/MM/YYYY";
313 1 : sExpected = "22/11/2542";
314 1 : checkPreviewString(aFormatter, sCode, fPreviewNumber, eLang, sExpected);
315 : }
316 : {
317 1 : sCode = "[~buddhist]D/MM/YY";
318 1 : sExpected = "22/11/42";
319 1 : checkPreviewString(aFormatter, sCode, fPreviewNumber, eLang, sExpected);
320 : }
321 : {
322 1 : sCode = "[NatNum1][$-41E][~buddhist]D/MM/YYYY";
323 : sal_Unicode sTemp[] =
324 : {
325 : 0x0E52, 0x0E52, 0x002F,
326 : 0x0E51, 0x0E51, 0x002F,
327 : 0x0E52, 0x0E55, 0x0E54, 0x0E52
328 1 : };
329 1 : sExpected = OUString(sTemp, SAL_N_ELEMENTS(sTemp));
330 1 : checkPreviewString(aFormatter, sCode, fPreviewNumber, eLang, sExpected);
331 : }
332 : {
333 1 : sCode = "[NatNum1][$-41E][~buddhist]D/MM/YY";
334 : sal_Unicode sTemp[] =
335 : {
336 : 0x0E52, 0x0E52, 0x002F,
337 : 0x0E51, 0x0E51, 0x002F,
338 : 0x0E54, 0x0E52
339 1 : };
340 1 : sExpected = OUString(sTemp, SAL_N_ELEMENTS(sTemp));
341 1 : checkPreviewString(aFormatter, sCode, fPreviewNumber, eLang, sExpected);
342 1 : }
343 1 : }
344 :
345 : // https://issues.apache.org/ooo/show_bug.cgi?id=116701
346 1 : void Test::testI116701()
347 : {
348 1 : LanguageType eLang = LANGUAGE_CHINESE_TRADITIONAL;
349 2 : OUString sCode, sExpected;
350 1 : double fPreviewNumber = 40573; // equals 30/01/2011
351 2 : SvNumberFormatter aFormatter(m_xContext, eLang);
352 : // DateFormatskey25 in i18npool/source/localedata/data/zh_TW.xml
353 : sal_Unicode CODE1[] =
354 : {
355 : 0x0047, 0x0047, 0x0047, 0x0045, 0x0045, // GGGEE
356 : 0x0022, 0x5E74, 0x0022,
357 : 0x004D, // M
358 : 0x0022, 0x6708, 0x0022,
359 : 0x0044, // D
360 : 0x0022, 0x65E5, 0x0022
361 1 : };
362 1 : sCode = OUString(CODE1, SAL_N_ELEMENTS(CODE1));
363 : sal_Unicode EXPECTED[] =
364 : {
365 : 0x4E2D, 0x83EF, 0x6C11, 0x570B,
366 : 0x0031, 0x0030, 0x0030, // 100
367 : 0x5E74,
368 : 0x0031, // 1
369 : 0x6708,
370 : 0x0033, 0x0030, // 30
371 : 0x65E5
372 1 : };
373 1 : sExpected = OUString(EXPECTED, SAL_N_ELEMENTS(EXPECTED));
374 1 : checkPreviewString(aFormatter, sCode, fPreviewNumber, eLang, sExpected);
375 : sal_Unicode CODE2[] =
376 : {
377 : 0x0047, 0x0047, 0x0047, 0x0045, // GGGE
378 : 0x0022, 0x5E74, 0x0022,
379 : 0x004D, // M
380 : 0x0022, 0x6708, 0x0022,
381 : 0x0044, // D
382 : 0x0022, 0x65E5, 0x0022
383 1 : };
384 1 : sCode = OUString(CODE2, SAL_N_ELEMENTS(CODE2));
385 2 : checkPreviewString(aFormatter, sCode, fPreviewNumber, eLang, sExpected);
386 1 : }
387 :
388 1 : CPPUNIT_TEST_SUITE_REGISTRATION(Test);
389 :
390 : }
391 :
392 4 : CPPUNIT_PLUGIN_IMPLEMENT();
393 :
394 : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|