1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2020 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the test suite of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:GPL-EXCEPT$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT |
21 | ** included in the packaging of this file. Please review the following |
22 | ** information to ensure the GNU General Public License requirements will |
23 | ** be met: https://www.gnu.org/licenses/gpl-3.0.html. |
24 | ** |
25 | ** $QT_END_LICENSE$ |
26 | ** |
27 | ****************************************************************************/ |
28 | |
29 | |
30 | #include <QtTest/QtTest> |
31 | #include <math.h> |
32 | #include <qdebug.h> |
33 | #include <qdir.h> |
34 | #include <qfileinfo.h> |
35 | #include <QScopedArrayPointer> |
36 | #include <qtextcodec.h> |
37 | #include <qdatetime.h> |
38 | #if QT_CONFIG(process) |
39 | # include <qprocess.h> |
40 | #endif |
41 | #include <float.h> |
42 | #include <locale.h> |
43 | |
44 | #include <qlocale.h> |
45 | #include <private/qlocale_p.h> |
46 | #include <private/qlocale_tools_p.h> |
47 | #include <qnumeric.h> |
48 | |
49 | #if defined(Q_OS_LINUX) && !defined(__UCLIBC__) |
50 | # define QT_USE_FENV |
51 | #endif |
52 | |
53 | #ifdef QT_USE_FENV |
54 | # include <fenv.h> |
55 | #endif |
56 | |
57 | #if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) |
58 | # include <stdlib.h> |
59 | #endif |
60 | |
61 | Q_DECLARE_METATYPE(QLocale::FormatType) |
62 | |
63 | class tst_QLocale : public QObject |
64 | { |
65 | Q_OBJECT |
66 | |
67 | public: |
68 | tst_QLocale(); |
69 | |
70 | private slots: |
71 | void initTestCase(); |
72 | void cleanupTestCase(); |
73 | #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) |
74 | void windowsDefaultLocale(); |
75 | #endif |
76 | #ifdef Q_OS_MAC |
77 | void macDefaultLocale(); |
78 | #endif |
79 | |
80 | void ctor(); |
81 | void emptyCtor_data(); |
82 | void emptyCtor(); |
83 | void consistentC(); |
84 | void matchingLocales(); |
85 | void stringToDouble_data(); |
86 | void stringToDouble(); |
87 | void stringToFloat_data(); |
88 | void stringToFloat(); |
89 | void doubleToString_data(); |
90 | void doubleToString(); |
91 | void strtod_data(); |
92 | void strtod(); |
93 | void long_long_conversion_data(); |
94 | void long_long_conversion(); |
95 | void long_long_conversion_extra(); |
96 | void testInfAndNan(); |
97 | void fpExceptions(); |
98 | void negativeZero(); |
99 | void dayOfWeek(); |
100 | void dayOfWeek_data(); |
101 | void formatDate(); |
102 | void formatDate_data(); |
103 | void formatTime(); |
104 | void formatTime_data(); |
105 | void formatDateTime(); |
106 | void formatDateTime_data(); |
107 | void formatTimeZone(); |
108 | void toDateTime_data(); |
109 | void toDateTime(); |
110 | void negativeNumbers(); |
111 | void numberOptions(); |
112 | void dayName_data(); |
113 | void dayName(); |
114 | void standaloneDayName_data(); |
115 | void standaloneDayName(); |
116 | void underflowOverflow(); |
117 | |
118 | void dateFormat(); |
119 | void timeFormat(); |
120 | void dateTimeFormat(); |
121 | void monthName(); |
122 | void standaloneMonthName(); |
123 | |
124 | void defaultNumberingSystem_data(); |
125 | void defaultNumberingSystem(); |
126 | |
127 | void ampm_data(); |
128 | void ampm(); |
129 | void currency(); |
130 | void quoteString(); |
131 | void uiLanguages(); |
132 | void weekendDays(); |
133 | void listPatterns(); |
134 | |
135 | void measurementSystems_data(); |
136 | void measurementSystems(); |
137 | void QTBUG_26035_positivesign(); |
138 | |
139 | void textDirection_data(); |
140 | void textDirection(); |
141 | |
142 | void formattedDataSize_data(); |
143 | void formattedDataSize(); |
144 | void bcp47Name_data(); |
145 | void bcp47Name(); |
146 | |
147 | void systemLocale_data(); |
148 | void systemLocale(); |
149 | |
150 | void IndianNumberGrouping(); |
151 | |
152 | // *** ORDER-DEPENDENCY *** (This Is Bad.) |
153 | // Test order is determined by order of declaration here: *all* tests that |
154 | // QLocale::setDefault() *must* appear *after* all other tests ! |
155 | void defaulted_ctor(); // This one must be the first of these. |
156 | void legacyNames(); |
157 | void unixLocaleName_data(); |
158 | void unixLocaleName(); |
159 | void testNames_data(); |
160 | void testNames(); |
161 | // DO NOT add tests here unless they QLocale::setDefault(); see above. |
162 | private: |
163 | QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; |
164 | QString m_sysapp; |
165 | QStringList cleanEnv; |
166 | bool europeanTimeZone; |
167 | void toReal_data(); |
168 | |
169 | class TransientLocale |
170 | { |
171 | const int m_category; |
172 | const char *const m_prior; |
173 | public: |
174 | TransientLocale(int category, const char *locale) |
175 | : m_category(category), m_prior(setlocale(category: category, locale: locale)) {} |
176 | ~TransientLocale() { setlocale(category: m_category, locale: m_prior); } |
177 | }; |
178 | }; |
179 | |
180 | tst_QLocale::tst_QLocale() |
181 | { |
182 | qRegisterMetaType<QLocale::FormatType>(typeName: "QLocale::FormatType" ); |
183 | |
184 | // Test if in Central European Time zone |
185 | uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toSecsSinceEpoch(); |
186 | uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toSecsSinceEpoch(); |
187 | europeanTimeZone = (x1 == 631148400 && x2 == 644191200); |
188 | } |
189 | |
190 | void tst_QLocale::initTestCase() |
191 | { |
192 | #if QT_CONFIG(process) |
193 | # ifdef Q_OS_ANDROID |
194 | m_sysapp = QCoreApplication::applicationDirPath() + "/libsyslocaleapp.so" ; |
195 | # else // !defined(Q_OS_ANDROID) |
196 | const QString syslocaleapp_dir = QFINDTESTDATA("syslocaleapp" ); |
197 | QVERIFY2(!syslocaleapp_dir.isEmpty(), |
198 | qPrintable(QStringLiteral("Cannot find 'syslocaleapp' starting from " ) |
199 | + QDir::toNativeSeparators(QDir::currentPath()))); |
200 | m_sysapp = syslocaleapp_dir + QStringLiteral("/syslocaleapp" ); |
201 | # ifdef Q_OS_WIN |
202 | m_sysapp += QStringLiteral(".exe" ); |
203 | # endif |
204 | # endif // Q_OS_ANDROID |
205 | const QFileInfo fi(m_sysapp); |
206 | QVERIFY2(fi.exists() && fi.isExecutable(), |
207 | qPrintable(QDir::toNativeSeparators(m_sysapp) |
208 | + QStringLiteral(" does not exist or is not executable." ))); |
209 | |
210 | // Get an environment free of any locale-related variables |
211 | cleanEnv.clear(); |
212 | foreach (QString const& entry, QProcess::systemEnvironment()) { |
213 | if (entry.startsWith(s: "LANG=" ) || entry.startsWith(s: "LC_" ) || entry.startsWith(s: "LANGUAGE=" )) |
214 | continue; |
215 | cleanEnv << entry; |
216 | } |
217 | #endif // QT_CONFIG(process) |
218 | } |
219 | |
220 | void tst_QLocale::cleanupTestCase() |
221 | {} |
222 | |
223 | void tst_QLocale::ctor() |
224 | { |
225 | QLocale default_locale = QLocale::system(); |
226 | QLocale::Language default_lang = default_locale.language(); |
227 | QLocale::Country default_country = default_locale.country(); |
228 | |
229 | qDebug(msg: "Default: %s/%s" , QLocale::languageToString(language: default_lang).toLatin1().constData(), |
230 | QLocale::countryToString(country: default_country).toLatin1().constData()); |
231 | |
232 | { |
233 | QLocale l; |
234 | QVERIFY(l.language() == default_lang); |
235 | QVERIFY(l.country() == default_country); |
236 | } |
237 | |
238 | #define TEST_CTOR(req_lang, req_script, req_country, exp_lang, exp_script, exp_country) \ |
239 | { \ |
240 | QLocale l(QLocale::req_lang, QLocale::req_script, QLocale::req_country); \ |
241 | QCOMPARE((int)l.language(), (int)exp_lang); \ |
242 | QCOMPARE((int)l.script(), (int)exp_script); \ |
243 | QCOMPARE((int)l.country(), (int)exp_country); \ |
244 | } |
245 | |
246 | // Exact matches |
247 | TEST_CTOR(Chinese, SimplifiedHanScript, China, |
248 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
249 | TEST_CTOR(Chinese, TraditionalHanScript, Taiwan, |
250 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan); |
251 | TEST_CTOR(Chinese, TraditionalHanScript, HongKong, |
252 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong); |
253 | |
254 | // Best match for AnyCountry |
255 | TEST_CTOR(Chinese, SimplifiedHanScript, AnyCountry, |
256 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
257 | TEST_CTOR(Chinese, TraditionalHanScript, AnyCountry, |
258 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan); |
259 | |
260 | // Best match for AnyScript (and change country to supported one, if necessary) |
261 | TEST_CTOR(Chinese, AnyScript, China, |
262 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
263 | TEST_CTOR(Chinese, AnyScript, Taiwan, |
264 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan); |
265 | TEST_CTOR(Chinese, AnyScript, HongKong, |
266 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::HongKong); |
267 | TEST_CTOR(Chinese, AnyScript, UnitedStates, |
268 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
269 | |
270 | // Fully-specified not found; find best alternate country |
271 | TEST_CTOR(Chinese, SimplifiedHanScript, Taiwan, |
272 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
273 | TEST_CTOR(Chinese, SimplifiedHanScript, UnitedStates, |
274 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
275 | TEST_CTOR(Chinese, TraditionalHanScript, China, |
276 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan); |
277 | TEST_CTOR(Chinese, TraditionalHanScript, UnitedStates, |
278 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan); |
279 | |
280 | // Fully-specified not found; find best alternate script |
281 | TEST_CTOR(Chinese, LatinScript, China, |
282 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
283 | TEST_CTOR(Chinese, LatinScript, Taiwan, |
284 | QLocale::Chinese, QLocale::TraditionalHanScript, QLocale::Taiwan); |
285 | |
286 | // Fully-specified not found; find best alternate country and script |
287 | TEST_CTOR(Chinese, LatinScript, UnitedStates, |
288 | QLocale::Chinese, QLocale::SimplifiedHanScript, QLocale::China); |
289 | |
290 | #undef TEST_CTOR |
291 | } |
292 | |
293 | void tst_QLocale::defaulted_ctor() |
294 | { |
295 | QLocale default_locale = QLocale::system(); |
296 | QLocale::Language default_lang = default_locale.language(); |
297 | QLocale::Country default_country = default_locale.country(); |
298 | |
299 | qDebug(msg: "Default: %s/%s" , QLocale::languageToString(language: default_lang).toLatin1().constData(), |
300 | QLocale::countryToString(country: default_country).toLatin1().constData()); |
301 | |
302 | { |
303 | QLocale l(QLocale::C, QLocale::AnyCountry); |
304 | QCOMPARE(l.language(), QLocale::C); |
305 | QCOMPARE(l.country(), QLocale::AnyCountry); |
306 | } |
307 | |
308 | #define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \ |
309 | { \ |
310 | QLocale l(QLocale::req_lang, QLocale::req_country); \ |
311 | QCOMPARE((int)l.language(), (int)exp_lang); \ |
312 | QCOMPARE((int)l.country(), (int)exp_country); \ |
313 | } |
314 | |
315 | TEST_CTOR(AnyLanguage, AnyCountry, default_lang, default_country) |
316 | TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) |
317 | TEST_CTOR(Aymara, AnyCountry, default_lang, default_country) |
318 | TEST_CTOR(Aymara, France, default_lang, default_country) |
319 | |
320 | TEST_CTOR(English, AnyCountry, QLocale::English, QLocale::UnitedStates) |
321 | TEST_CTOR(English, UnitedStates, QLocale::English, QLocale::UnitedStates) |
322 | TEST_CTOR(English, France, QLocale::English, QLocale::UnitedStates) |
323 | TEST_CTOR(English, UnitedKingdom, QLocale::English, QLocale::UnitedKingdom) |
324 | |
325 | TEST_CTOR(French, France, QLocale::French, QLocale::France) |
326 | TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry) |
327 | TEST_CTOR(Spanish, LatinAmerica, QLocale::Spanish, |
328 | QLocale::LatinAmerica) |
329 | |
330 | QLocale::setDefault(QLocale(QLocale::English, QLocale::France)); |
331 | |
332 | { |
333 | QLocale l; |
334 | QVERIFY(l.language() == QLocale::English); |
335 | QVERIFY(l.country() == QLocale::UnitedStates); |
336 | } |
337 | |
338 | TEST_CTOR(French, France, QLocale::French, QLocale::France) |
339 | TEST_CTOR(English, UnitedKingdom, QLocale::English, QLocale::UnitedKingdom) |
340 | |
341 | TEST_CTOR(French, France, QLocale::French, QLocale::France) |
342 | TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) |
343 | TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry) |
344 | TEST_CTOR(Aymara, AnyCountry, QLocale::English, QLocale::UnitedStates) |
345 | |
346 | QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedKingdom)); |
347 | |
348 | { |
349 | QLocale l; |
350 | QVERIFY(l.language() == QLocale::English); |
351 | QVERIFY(l.country() == QLocale::UnitedKingdom); |
352 | } |
353 | |
354 | TEST_CTOR(French, France, QLocale::French, QLocale::France) |
355 | TEST_CTOR(English, UnitedKingdom, QLocale::English, QLocale::UnitedKingdom) |
356 | |
357 | TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) |
358 | TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry) |
359 | |
360 | QLocale::setDefault(QLocale(QLocale::Aymara, QLocale::France)); |
361 | |
362 | { |
363 | QLocale l; |
364 | QVERIFY(l.language() == QLocale::English); |
365 | QVERIFY(l.country() == QLocale::UnitedKingdom); |
366 | } |
367 | |
368 | TEST_CTOR(Aymara, AnyCountry, QLocale::English, QLocale::UnitedKingdom) |
369 | TEST_CTOR(Aymara, France, QLocale::English, QLocale::UnitedKingdom) |
370 | |
371 | TEST_CTOR(English, AnyCountry, QLocale::English, QLocale::UnitedStates) |
372 | TEST_CTOR(English, UnitedStates, QLocale::English, QLocale::UnitedStates) |
373 | TEST_CTOR(English, France, QLocale::English, QLocale::UnitedStates) |
374 | TEST_CTOR(English, UnitedKingdom, QLocale::English, QLocale::UnitedKingdom) |
375 | |
376 | TEST_CTOR(French, France, QLocale::French, QLocale::France) |
377 | TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) |
378 | TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry) |
379 | |
380 | QLocale::setDefault(QLocale(QLocale::Aymara, QLocale::AnyCountry)); |
381 | |
382 | { |
383 | QLocale l; |
384 | QVERIFY(l.language() == QLocale::English); |
385 | QVERIFY(l.country() == QLocale::UnitedKingdom); |
386 | } |
387 | |
388 | TEST_CTOR(Aymara, AnyCountry, QLocale::English, QLocale::UnitedKingdom) |
389 | TEST_CTOR(Aymara, France, QLocale::English, QLocale::UnitedKingdom) |
390 | |
391 | TEST_CTOR(English, AnyCountry, QLocale::English, QLocale::UnitedStates) |
392 | TEST_CTOR(English, UnitedStates, QLocale::English, QLocale::UnitedStates) |
393 | TEST_CTOR(English, France, QLocale::English, QLocale::UnitedStates) |
394 | TEST_CTOR(English, UnitedKingdom, QLocale::English, QLocale::UnitedKingdom) |
395 | |
396 | TEST_CTOR(French, France, QLocale::French, QLocale::France) |
397 | TEST_CTOR(C, AnyCountry, QLocale::C, QLocale::AnyCountry) |
398 | TEST_CTOR(C, France, QLocale::C, QLocale::AnyCountry) |
399 | |
400 | TEST_CTOR(Arabic, AnyCountry, QLocale::Arabic, QLocale::Egypt) |
401 | TEST_CTOR(Dutch, AnyCountry, QLocale::Dutch, QLocale::Netherlands) |
402 | TEST_CTOR(German, AnyCountry, QLocale::German, QLocale::Germany) |
403 | TEST_CTOR(Greek, AnyCountry, QLocale::Greek, QLocale::Greece) |
404 | TEST_CTOR(Malay, AnyCountry, QLocale::Malay, QLocale::Malaysia) |
405 | TEST_CTOR(Persian, AnyCountry, QLocale::Persian, QLocale::Iran) |
406 | TEST_CTOR(Portuguese, AnyCountry, QLocale::Portuguese, QLocale::Brazil) |
407 | TEST_CTOR(Serbian, AnyCountry, QLocale::Serbian, QLocale::Serbia) |
408 | TEST_CTOR(Somali, AnyCountry, QLocale::Somali, QLocale::Somalia) |
409 | TEST_CTOR(Spanish, AnyCountry, QLocale::Spanish, QLocale::Spain) |
410 | TEST_CTOR(Swedish, AnyCountry, QLocale::Swedish, QLocale::Sweden) |
411 | TEST_CTOR(Uzbek, AnyCountry, QLocale::Uzbek, QLocale::Uzbekistan) |
412 | |
413 | #undef TEST_CTOR |
414 | #define TEST_CTOR(req_lc, exp_lang, exp_country) \ |
415 | { \ |
416 | QLocale l(req_lc); \ |
417 | QVERIFY2(l.language() == QLocale::exp_lang \ |
418 | && l.country() == QLocale::exp_country, \ |
419 | QString("requested: \"" + QString(req_lc) + "\", got: " \ |
420 | + QLocale::languageToString(l.language()) \ |
421 | + QLatin1Char('/') \ |
422 | + QLocale::countryToString(l.country())).toLatin1().constData()); \ |
423 | QCOMPARE(l, QLocale(QLocale::exp_lang, QLocale::exp_country)); \ |
424 | QCOMPARE(qHash(l), qHash(QLocale(QLocale::exp_lang, QLocale::exp_country))); \ |
425 | } |
426 | |
427 | QLocale::setDefault(QLocale(QLocale::C)); |
428 | const QString empty; |
429 | |
430 | TEST_CTOR("C" , C, AnyCountry) |
431 | TEST_CTOR("bla" , C, AnyCountry) |
432 | TEST_CTOR("zz" , C, AnyCountry) |
433 | TEST_CTOR("zz_zz" , C, AnyCountry) |
434 | TEST_CTOR("zz..." , C, AnyCountry) |
435 | TEST_CTOR("" , C, AnyCountry) |
436 | TEST_CTOR("en/" , C, AnyCountry) |
437 | TEST_CTOR(empty, C, AnyCountry) |
438 | TEST_CTOR("en" , English, UnitedStates) |
439 | TEST_CTOR("en" , English, UnitedStates) |
440 | TEST_CTOR("en." , English, UnitedStates) |
441 | TEST_CTOR("en@" , English, UnitedStates) |
442 | TEST_CTOR("en.@" , English, UnitedStates) |
443 | TEST_CTOR("en_" , English, UnitedStates) |
444 | TEST_CTOR("en_U" , English, UnitedStates) |
445 | TEST_CTOR("en_." , English, UnitedStates) |
446 | TEST_CTOR("en_.@" , English, UnitedStates) |
447 | TEST_CTOR("en.bla" , English, UnitedStates) |
448 | TEST_CTOR("en@bla" , English, UnitedStates) |
449 | TEST_CTOR("en_blaaa" , English, UnitedStates) |
450 | TEST_CTOR("en_zz" , English, UnitedStates) |
451 | TEST_CTOR("en_GB" , English, UnitedKingdom) |
452 | TEST_CTOR("en_GB.bla" , English, UnitedKingdom) |
453 | TEST_CTOR("en_GB@.bla" , English, UnitedKingdom) |
454 | TEST_CTOR("en_GB@bla" , English, UnitedKingdom) |
455 | TEST_CTOR("en-GB" , English, UnitedKingdom) |
456 | TEST_CTOR("en-GB@bla" , English, UnitedKingdom) |
457 | TEST_CTOR("eo" , Esperanto, World) |
458 | TEST_CTOR("yi" , Yiddish, World) |
459 | |
460 | TEST_CTOR("no" , NorwegianBokmal, Norway) |
461 | TEST_CTOR("nb" , NorwegianBokmal, Norway) |
462 | TEST_CTOR("nn" , NorwegianNynorsk, Norway) |
463 | TEST_CTOR("no_NO" , NorwegianBokmal, Norway) |
464 | TEST_CTOR("nb_NO" , NorwegianBokmal, Norway) |
465 | TEST_CTOR("nn_NO" , NorwegianNynorsk, Norway) |
466 | TEST_CTOR("es_ES" , Spanish, Spain) |
467 | TEST_CTOR("es_419" , Spanish, LatinAmerica) |
468 | TEST_CTOR("es-419" , Spanish, LatinAmerica) |
469 | TEST_CTOR("fr_MA" , French, Morocco) |
470 | |
471 | // test default countries for languages |
472 | TEST_CTOR("zh" , Chinese, China) |
473 | TEST_CTOR("zh-Hans" , Chinese, China) |
474 | TEST_CTOR("ne" , Nepali, Nepal) |
475 | |
476 | #undef TEST_CTOR |
477 | #define TEST_CTOR(req_lc, exp_lang, exp_script, exp_country) \ |
478 | { \ |
479 | QLocale l(req_lc); \ |
480 | QVERIFY2(l.language() == QLocale::exp_lang \ |
481 | && l.script() == QLocale::exp_script \ |
482 | && l.country() == QLocale::exp_country, \ |
483 | QString("requested: \"" + QString(req_lc) + "\", got: " \ |
484 | + QLocale::languageToString(l.language()) \ |
485 | + QLatin1Char('/') + QLocale::scriptToString(l.script()) \ |
486 | + QLatin1Char('/') + QLocale::countryToString(l.country())).toLatin1().constData()); \ |
487 | } |
488 | |
489 | TEST_CTOR("zh_CN" , Chinese, SimplifiedHanScript, China) |
490 | TEST_CTOR("zh_Hans_CN" , Chinese, SimplifiedHanScript, China) |
491 | TEST_CTOR("zh_Hans" , Chinese, SimplifiedHanScript, China) |
492 | TEST_CTOR("zh_Hant" , Chinese, TraditionalHanScript, Taiwan) |
493 | TEST_CTOR("zh_Hans_MO" , Chinese, SimplifiedHanScript, Macau) |
494 | TEST_CTOR("zh_Hant_MO" , Chinese, TraditionalHanScript, Macau) |
495 | TEST_CTOR("az_Latn_AZ" , Azerbaijani, LatinScript, Azerbaijan) |
496 | TEST_CTOR("ha_NG" , Hausa, LatinScript, Nigeria) |
497 | |
498 | TEST_CTOR("ru" , Russian, CyrillicScript, RussianFederation) |
499 | TEST_CTOR("ru_Cyrl" , Russian, CyrillicScript, RussianFederation) |
500 | |
501 | #undef TEST_CTOR |
502 | } |
503 | |
504 | #if QT_CONFIG(process) |
505 | static inline bool runSysApp(const QString &binary, |
506 | const QStringList &env, |
507 | QString *output, |
508 | QString *errorMessage) |
509 | { |
510 | output->clear(); |
511 | errorMessage->clear(); |
512 | QProcess process; |
513 | process.setEnvironment(env); |
514 | process.start(program: binary, arguments: QStringList()); |
515 | process.closeWriteChannel(); |
516 | if (!process.waitForStarted()) { |
517 | *errorMessage = QLatin1String("Cannot start '" ) + binary |
518 | + QLatin1String("': " ) + process.errorString(); |
519 | return false; |
520 | } |
521 | if (!process.waitForFinished()) { |
522 | process.kill(); |
523 | *errorMessage = QStringLiteral("Timeout waiting for " ) + binary; |
524 | return false; |
525 | } |
526 | *output = QString::fromLocal8Bit(str: process.readAllStandardOutput()); |
527 | return true; |
528 | } |
529 | |
530 | static inline bool runSysAppTest(const QString &binary, |
531 | QStringList baseEnv, |
532 | const QString &requestedLocale, |
533 | const QString &expectedOutput, |
534 | QString *errorMessage) |
535 | { |
536 | QString output; |
537 | baseEnv.append(QStringLiteral("LANG=" ) + requestedLocale); |
538 | if (!runSysApp(binary, env: baseEnv, output: &output, errorMessage)) |
539 | return false; |
540 | |
541 | if (output.isEmpty()) { |
542 | *errorMessage = QLatin1String("Empty output received for requested '" ) + requestedLocale |
543 | + QLatin1String("' (expected '" ) + expectedOutput + QLatin1String("')" ); |
544 | return false; |
545 | } |
546 | if (output != expectedOutput) { |
547 | *errorMessage = QLatin1String("Output mismatch for requested '" ) + requestedLocale |
548 | + QLatin1String("': Expected '" ) + expectedOutput + QLatin1String("', got '" ) |
549 | + output + QLatin1String("'" ); |
550 | return false; |
551 | } |
552 | return true; |
553 | } |
554 | #endif |
555 | |
556 | void tst_QLocale::emptyCtor_data() |
557 | { |
558 | #if !QT_CONFIG(process) |
559 | QSKIP("No qprocess support" , SkipAll); |
560 | #endif |
561 | #ifdef Q_OS_ANDROID |
562 | QSKIP("This test crashes on Android" ); |
563 | #endif |
564 | |
565 | QTest::addColumn<QString>(name: "expected" ); |
566 | |
567 | #define ADD_CTOR_TEST(give, expect) QTest::newRow(give) << QStringLiteral(expect); |
568 | |
569 | // For format and meaning, see: |
570 | // http://pubs.opengroup.org/onlinepubs/7908799/xbd/envvar.html |
571 | // Note that the accepted values for fields are implementation-dependent; |
572 | // the template is language[_territory][.codeset][@modifier] |
573 | |
574 | // Vanilla: |
575 | ADD_CTOR_TEST("C" , "C" ); |
576 | |
577 | // Standard forms: |
578 | ADD_CTOR_TEST("en" , "en_US" ); |
579 | ADD_CTOR_TEST("en_GB" , "en_GB" ); |
580 | ADD_CTOR_TEST("de" , "de_DE" ); |
581 | // Norsk has some quirks: |
582 | ADD_CTOR_TEST("no" , "nb_NO" ); |
583 | ADD_CTOR_TEST("nb" , "nb_NO" ); |
584 | ADD_CTOR_TEST("nn" , "nn_NO" ); |
585 | ADD_CTOR_TEST("no_NO" , "nb_NO" ); |
586 | ADD_CTOR_TEST("nb_NO" , "nb_NO" ); |
587 | ADD_CTOR_TEST("nn_NO" , "nn_NO" ); |
588 | |
589 | // Not too fussy about case: |
590 | ADD_CTOR_TEST("DE" , "de_DE" ); |
591 | ADD_CTOR_TEST("EN" , "en_US" ); |
592 | |
593 | // Invalid fields |
594 | ADD_CTOR_TEST("bla" , "C" ); |
595 | ADD_CTOR_TEST("zz" , "C" ); |
596 | ADD_CTOR_TEST("zz_zz" , "C" ); |
597 | ADD_CTOR_TEST("zz..." , "C" ); |
598 | ADD_CTOR_TEST("en.bla" , "en_US" ); |
599 | ADD_CTOR_TEST("en@bla" , "en_US" ); |
600 | ADD_CTOR_TEST("en_blaaa" , "en_US" ); |
601 | ADD_CTOR_TEST("en_zz" , "en_US" ); |
602 | ADD_CTOR_TEST("en_GB.bla" , "en_GB" ); |
603 | ADD_CTOR_TEST("en_GB@.bla" , "en_GB" ); |
604 | ADD_CTOR_TEST("en_GB@bla" , "en_GB" ); |
605 | |
606 | // Empty optional fields, but with punctuators supplied |
607 | ADD_CTOR_TEST("en." , "en_US" ); |
608 | ADD_CTOR_TEST("en@" , "en_US" ); |
609 | ADD_CTOR_TEST("en.@" , "en_US" ); |
610 | ADD_CTOR_TEST("en_" , "en_US" ); |
611 | ADD_CTOR_TEST("en_." , "en_US" ); |
612 | ADD_CTOR_TEST("en_.@" , "en_US" ); |
613 | #undef ADD_CTOR_TEST |
614 | |
615 | #if QT_CONFIG(process) // for runSysApp |
616 | // Get default locale. |
617 | QString defaultLoc; |
618 | QString errorMessage; |
619 | if (runSysApp(binary: m_sysapp, env: cleanEnv, output: &defaultLoc, errorMessage: &errorMessage)) { |
620 | #define ADD_CTOR_TEST(give) QTest::newRow(give) << defaultLoc; |
621 | ADD_CTOR_TEST("en/" ); |
622 | ADD_CTOR_TEST("asdfghj" ); |
623 | ADD_CTOR_TEST("123456" ); |
624 | #undef ADD_CTOR_TEST |
625 | } else { |
626 | qDebug() << "Skipping tests based on default locale" << qPrintable(errorMessage); |
627 | } |
628 | #endif // process |
629 | } |
630 | |
631 | void tst_QLocale::emptyCtor() |
632 | { |
633 | #if QT_CONFIG(process) // for runSysAppTest |
634 | QLatin1String request(QTest::currentDataTag()); |
635 | QFETCH(QString, expected); |
636 | |
637 | // Test constructor without arguments (see syslocaleapp/syslocaleapp.cpp) |
638 | // Needs separate process because of caching of the system locale. |
639 | QString errorMessage; |
640 | QVERIFY2(runSysAppTest(m_sysapp, cleanEnv, request, expected, &errorMessage), |
641 | qPrintable(errorMessage)); |
642 | |
643 | #else |
644 | // This won't be called, as _data() skipped out early. |
645 | #endif // process |
646 | } |
647 | |
648 | void tst_QLocale::legacyNames() |
649 | { |
650 | QLocale::setDefault(QLocale(QLocale::C)); |
651 | |
652 | #if QT_DEPRECATED_SINCE(5, 15) |
653 | #define TEST_CTOR(req_lang, req_country, exp_lang, exp_country) \ |
654 | { \ |
655 | QLocale l(QLocale::req_lang, QLocale::req_country); \ |
656 | QCOMPARE((int)l.language(), (int)QLocale::exp_lang); \ |
657 | QCOMPARE((int)l.country(), (int)QLocale::exp_country); \ |
658 | } |
659 | |
660 | TEST_CTOR(Moldavian, Moldova, Romanian, Moldova) |
661 | TEST_CTOR(Norwegian, AnyCountry, Norwegian, Norway) |
662 | TEST_CTOR(SerboCroatian, Montenegro, Serbian, Montenegro) |
663 | TEST_CTOR(Tagalog, AnyCountry, Filipino, Philippines) |
664 | |
665 | #undef TEST_CTOR |
666 | #endif |
667 | |
668 | #define TEST_CTOR(req_lc, exp_lang, exp_country) \ |
669 | { \ |
670 | QLocale l(req_lc); \ |
671 | QVERIFY2(l.language() == QLocale::exp_lang \ |
672 | && l.country() == QLocale::exp_country, \ |
673 | QString("requested: \"" + QString(req_lc) + "\", got: " \ |
674 | + QLocale::languageToString(l.language()) \ |
675 | + QLatin1Char('/') \ |
676 | + QLocale::countryToString(l.country())).toLatin1().constData()); \ |
677 | } |
678 | |
679 | TEST_CTOR("mo_MD" , Romanian, Moldova) |
680 | TEST_CTOR("no" , NorwegianBokmal, Norway) |
681 | TEST_CTOR("sh_ME" , Serbian, Montenegro) |
682 | TEST_CTOR("tl" , Filipino, Philippines) |
683 | TEST_CTOR("iw" , Hebrew, Israel) |
684 | TEST_CTOR("in" , Indonesian, Indonesia) |
685 | #undef TEST_CTOR |
686 | } |
687 | |
688 | void tst_QLocale::consistentC() |
689 | { |
690 | const QLocale c(QLocale::C); |
691 | QCOMPARE(c, QLocale::c()); |
692 | QCOMPARE(c, QLocale(QLocale::C, QLocale::AnyScript, QLocale::AnyCountry)); |
693 | QVERIFY(QLocale::matchingLocales(QLocale::AnyLanguage, QLocale::AnyScript, |
694 | QLocale::AnyCountry).contains(c)); |
695 | } |
696 | |
697 | void tst_QLocale::matchingLocales() |
698 | { |
699 | const QLocale c(QLocale::C); |
700 | const QLocale ru_RU(QLocale::Russian, QLocale::Russia); |
701 | |
702 | QList<QLocale> locales = QLocale::matchingLocales(language: QLocale::C, script: QLocale::AnyScript, country: QLocale::AnyCountry); |
703 | QCOMPARE(locales.size(), 1); |
704 | QVERIFY(locales.contains(c)); |
705 | |
706 | locales = QLocale::matchingLocales(language: QLocale::Russian, script: QLocale::CyrillicScript, country: QLocale::Russia); |
707 | QCOMPARE(locales.size(), 1); |
708 | QVERIFY(locales.contains(ru_RU)); |
709 | |
710 | locales = QLocale::matchingLocales(language: QLocale::Russian, script: QLocale::AnyScript, country: QLocale::AnyCountry); |
711 | QVERIFY(!locales.isEmpty()); |
712 | QVERIFY(!locales.contains(c)); |
713 | QVERIFY(locales.contains(ru_RU)); |
714 | |
715 | locales = QLocale::matchingLocales(language: QLocale::AnyLanguage, script: QLocale::CyrillicScript, country: QLocale::AnyCountry); |
716 | QVERIFY(!locales.isEmpty()); |
717 | QVERIFY(!locales.contains(c)); |
718 | QVERIFY(locales.contains(ru_RU)); |
719 | |
720 | locales = QLocale::matchingLocales(language: QLocale::AnyLanguage, script: QLocale::AnyScript, country: QLocale::Russia); |
721 | QVERIFY(!locales.isEmpty()); |
722 | QVERIFY(!locales.contains(c)); |
723 | QVERIFY(locales.contains(ru_RU)); |
724 | } |
725 | |
726 | void tst_QLocale::unixLocaleName_data() |
727 | { |
728 | QTest::addColumn<QLocale::Language>(name: "lang" ); |
729 | QTest::addColumn<QLocale::Country>(name: "land" ); |
730 | QTest::addColumn<QString>(name: "expect" ); |
731 | |
732 | #define ADDROW(nom, lang, land, name) \ |
733 | QTest::newRow(nom) << QLocale::lang << QLocale::land << QStringLiteral(name) |
734 | |
735 | ADDROW("C_any" , C, AnyCountry, "C" ); |
736 | ADDROW("en_any" , English, AnyCountry, "en_US" ); |
737 | ADDROW("en_GB" , English, UnitedKingdom, "en_GB" ); |
738 | ADDROW("ay_GB" , Aymara, UnitedKingdom, "C" ); |
739 | #undef ADDROW |
740 | } |
741 | |
742 | void tst_QLocale::unixLocaleName() |
743 | { |
744 | QFETCH(QLocale::Language, lang); |
745 | QFETCH(QLocale::Country, land); |
746 | QFETCH(QString, expect); |
747 | |
748 | QLocale::setDefault(QLocale(QLocale::C)); |
749 | |
750 | QLocale locale(lang, land); |
751 | QCOMPARE(locale.name(), expect); |
752 | } |
753 | |
754 | void tst_QLocale::toReal_data() |
755 | { |
756 | QTest::addColumn<QString>(name: "locale_name" ); |
757 | QTest::addColumn<QString>(name: "num_str" ); |
758 | QTest::addColumn<bool>(name: "good" ); |
759 | QTest::addColumn<double>(name: "num" ); |
760 | |
761 | QTest::newRow(dataTag: "C 1" ) << QString("C" ) << QString("1" ) << true << 1.0; |
762 | QTest::newRow(dataTag: "C 1.0" ) << QString("C" ) << QString("1.0" ) << true << 1.0; |
763 | QTest::newRow(dataTag: "C 1.234" ) << QString("C" ) << QString("1.234" ) << true << 1.234; |
764 | QTest::newRow(dataTag: "C 1.234e-10" ) << QString("C" ) << QString("1.234e-10" ) << true << 1.234e-10; |
765 | QTest::newRow(dataTag: "C 1.234E10" ) << QString("C" ) << QString("1.234E10" ) << true << 1.234e10; |
766 | QTest::newRow(dataTag: "C 1e10" ) << QString("C" ) << QString("1e10" ) << true << 1.0e10; |
767 | QTest::newRow(dataTag: "C 1e310" ) << QString("C" ) << QString("1e310" ) << false << std::numeric_limits<double>::infinity(); |
768 | QTest::newRow(dataTag: "C 1E310" ) << QString("C" ) << QString("1E310" ) << false << std::numeric_limits<double>::infinity(); |
769 | QTest::newRow(dataTag: "C 1" ) << QString("C" ) << QString(" 1" ) << true << 1.0; |
770 | QTest::newRow(dataTag: "C 1" ) << QString("C" ) << QString(" 1" ) << true << 1.0; |
771 | QTest::newRow(dataTag: "C 1 " ) << QString("C" ) << QString("1 " ) << true << 1.0; |
772 | QTest::newRow(dataTag: "C 1 " ) << QString("C" ) << QString("1 " ) << true << 1.0; |
773 | |
774 | QTest::newRow(dataTag: "C 1," ) << QString("C" ) << QString("1," ) << false << 0.0; |
775 | QTest::newRow(dataTag: "C 1,2" ) << QString("C" ) << QString("1,2" ) << false << 0.0; |
776 | QTest::newRow(dataTag: "C 1,23" ) << QString("C" ) << QString("1,23" ) << false << 0.0; |
777 | QTest::newRow(dataTag: "C 1,234" ) << QString("C" ) << QString("1,234" ) << true << 1234.0; |
778 | QTest::newRow(dataTag: "C 1,234," ) << QString("C" ) << QString("1,234," ) << false << 0.0; |
779 | QTest::newRow(dataTag: "C 1,234,5" ) << QString("C" ) << QString("1,234,5" ) << false << 0.0; |
780 | QTest::newRow(dataTag: "C 1,234,56" ) << QString("C" ) << QString("1,234,56" ) << false << 0.0; |
781 | QTest::newRow(dataTag: "C 1,234,567" ) << QString("C" ) << QString("1,234,567" ) << true << 1234567.0; |
782 | QTest::newRow(dataTag: "C 1,234,567." ) << QString("C" ) << QString("1,234,567." ) << true << 1234567.0; |
783 | QTest::newRow(dataTag: "C 1,234,567.8" ) << QString("C" ) << QString("1,234,567.8" ) << true << 1234567.8; |
784 | QTest::newRow(dataTag: "C 1,234567.8" ) << QString("C" ) << QString("1,234567.8" ) << false << 0.0; |
785 | QTest::newRow(dataTag: "C 12,34567.8" ) << QString("C" ) << QString("12,34567.8" ) << false << 0.0; |
786 | QTest::newRow(dataTag: "C 1234,567.8" ) << QString("C" ) << QString("1234,567.8" ) << false << 0.0; |
787 | QTest::newRow(dataTag: "C 1234567.8" ) << QString("C" ) << QString("1234567.8" ) << true << 1234567.8; |
788 | QTest::newRow(dataTag: "C ," ) << QString("C" ) << QString("," ) << false << 0.0; |
789 | QTest::newRow(dataTag: "C ,123" ) << QString("C" ) << QString(",123" ) << false << 0.0; |
790 | QTest::newRow(dataTag: "C ,3" ) << QString("C" ) << QString(",3" ) << false << 0.0; |
791 | QTest::newRow(dataTag: "C , 3" ) << QString("C" ) << QString(", 3" ) << false << 0.0; |
792 | QTest::newRow(dataTag: "C , 3" ) << QString("C" ) << QString(", 3" ) << false << 0.0; |
793 | QTest::newRow(dataTag: "C , 3.2" ) << QString("C" ) << QString(", 3.2" ) << false << 0.0; |
794 | QTest::newRow(dataTag: "C , 3.2e2" ) << QString("C" ) << QString(", 3.2e2" ) << false << 0.0; |
795 | QTest::newRow(dataTag: "C , e2" ) << QString("C" ) << QString(", e2" ) << false << 0.0; |
796 | QTest::newRow(dataTag: "C 1,,234" ) << QString("C" ) << QString("1,,234" ) << false << 0.0; |
797 | |
798 | QTest::newRow(dataTag: "C empty" ) << QString("C" ) << QString("" ) << false << 0.0; |
799 | QTest::newRow(dataTag: "C null" ) << QString("C" ) << QString() << false << 0.0; |
800 | QTest::newRow(dataTag: "C ." ) << QString("C" ) << QString("." ) << false << 0.0; |
801 | QTest::newRow(dataTag: "C 1e" ) << QString("C" ) << QString("1e" ) << false << 0.0; |
802 | QTest::newRow(dataTag: "C 1,0" ) << QString("C" ) << QString("1,0" ) << false << 0.0; |
803 | QTest::newRow(dataTag: "C 1,000" ) << QString("C" ) << QString("1,000" ) << true << 1000.0; |
804 | QTest::newRow(dataTag: "C 1,000e-6" ) << QString("C" ) << QString("1,000e-6" ) << true << 1000.0e-6; |
805 | QTest::newRow(dataTag: "C 1e1.0" ) << QString("C" ) << QString("1e1.0" ) << false << 0.0; |
806 | QTest::newRow(dataTag: "C 1e+" ) << QString("C" ) << QString("1e+" ) << false << 0.0; |
807 | QTest::newRow(dataTag: "C 1e-" ) << QString("C" ) << QString("1e-" ) << false << 0.0; |
808 | |
809 | QTest::newRow(dataTag: "C .1" ) << QString("C" ) << QString(".1" ) << true << 0.1; |
810 | QTest::newRow(dataTag: "C -.1" ) << QString("C" ) << QString("-.1" ) << true << -0.1; |
811 | QTest::newRow(dataTag: "C 1." ) << QString("C" ) << QString("1." ) << true << 1.0; |
812 | QTest::newRow(dataTag: "C 1.E10" ) << QString("C" ) << QString("1.E10" ) << true << 1.0e10; |
813 | QTest::newRow(dataTag: "C 1e+10" ) << QString("C" ) << QString("1e+10" ) << true << 1.0e+10; |
814 | |
815 | QTest::newRow(dataTag: "de_DE 1." ) << QString("de_DE" ) << QString("1." ) << false << 0.0; |
816 | QTest::newRow(dataTag: "de_DE 1.2" ) << QString("de_DE" ) << QString("1.2" ) << false << 0.0; |
817 | QTest::newRow(dataTag: "de_DE 1.23" ) << QString("de_DE" ) << QString("1.23" ) << false << 0.0; |
818 | QTest::newRow(dataTag: "de_DE 1.234" ) << QString("de_DE" ) << QString("1.234" ) << true << 1234.0; |
819 | QTest::newRow(dataTag: "de_DE 1.234," ) << QString("de_DE" ) << QString("1.234." ) << false << 0.0; |
820 | QTest::newRow(dataTag: "de_DE 1.234.5" ) << QString("de_DE" ) << QString("1.234.5" ) << false << 0.0; |
821 | QTest::newRow(dataTag: "de_DE 1.234.56" ) << QString("de_DE" ) << QString("1.234.56" ) << false << 0.0; |
822 | QTest::newRow(dataTag: "de_DE 1.234.567" ) << QString("de_DE" ) << QString("1.234.567" ) << true << 1234567.0; |
823 | QTest::newRow(dataTag: "de_DE 1.234.567," ) << QString("de_DE" ) << QString("1.234.567," ) << true << 1234567.0; |
824 | QTest::newRow(dataTag: "de_DE 1.234.567,8" ) << QString("de_DE" ) << QString("1.234.567,8" ) << true << 1234567.8; |
825 | QTest::newRow(dataTag: "de_DE 1.234567,8" ) << QString("de_DE" ) << QString("1.234567,8" ) << false << 0.0; |
826 | QTest::newRow(dataTag: "de_DE 12.34567,8" ) << QString("de_DE" ) << QString("12.34567,8" ) << false << 0.0; |
827 | QTest::newRow(dataTag: "de_DE 1234.567,8" ) << QString("de_DE" ) << QString("1234.567,8" ) << false << 0.0; |
828 | QTest::newRow(dataTag: "de_DE 1234567,8" ) << QString("de_DE" ) << QString("1234567,8" ) << true << 1234567.8; |
829 | QTest::newRow(dataTag: "de_DE .123" ) << QString("de_DE" ) << QString(".123" ) << false << 0.0; |
830 | QTest::newRow(dataTag: "de_DE .3" ) << QString("de_DE" ) << QString(".3" ) << false << 0.0; |
831 | QTest::newRow(dataTag: "de_DE . 3" ) << QString("de_DE" ) << QString(". 3" ) << false << 0.0; |
832 | QTest::newRow(dataTag: "de_DE . 3" ) << QString("de_DE" ) << QString(". 3" ) << false << 0.0; |
833 | QTest::newRow(dataTag: "de_DE . 3,2" ) << QString("de_DE" ) << QString(". 3,2" ) << false << 0.0; |
834 | QTest::newRow(dataTag: "de_DE . 3,2e2" ) << QString("de_DE" ) << QString(". 3,2e2" ) << false << 0.0; |
835 | QTest::newRow(dataTag: "de_DE . e2" ) << QString("de_DE" ) << QString(". e2" ) << false << 0.0; |
836 | QTest::newRow(dataTag: "de_DE 1..234" ) << QString("de_DE" ) << QString("1..234" ) << false << 0.0; |
837 | |
838 | QTest::newRow(dataTag: "de_DE 1" ) << QString("de_DE" ) << QString("1" ) << true << 1.0; |
839 | QTest::newRow(dataTag: "de_DE 1.0" ) << QString("de_DE" ) << QString("1.0" ) << false << 0.0; |
840 | QTest::newRow(dataTag: "de_DE 1.234e-10" ) << QString("de_DE" ) << QString("1.234e-10" ) << true << 1234.0e-10; |
841 | QTest::newRow(dataTag: "de_DE 1.234E10" ) << QString("de_DE" ) << QString("1.234E10" ) << true << 1234.0e10; |
842 | QTest::newRow(dataTag: "de_DE 1e10" ) << QString("de_DE" ) << QString("1e10" ) << true << 1.0e10; |
843 | QTest::newRow(dataTag: "de_DE .1" ) << QString("de_DE" ) << QString(".1" ) << false << 0.0; |
844 | QTest::newRow(dataTag: "de_DE -.1" ) << QString("de_DE" ) << QString("-.1" ) << false << 0.0; |
845 | QTest::newRow(dataTag: "de_DE 1.E10" ) << QString("de_DE" ) << QString("1.E10" ) << false << 0.0; |
846 | QTest::newRow(dataTag: "de_DE 1e+10" ) << QString("de_DE" ) << QString("1e+10" ) << true << 1.0e+10; |
847 | |
848 | QTest::newRow(dataTag: "de_DE 1,0" ) << QString("de_DE" ) << QString("1,0" ) << true << 1.0; |
849 | QTest::newRow(dataTag: "de_DE 1,234" ) << QString("de_DE" ) << QString("1,234" ) << true << 1.234; |
850 | QTest::newRow(dataTag: "de_DE 1,234e-10" ) << QString("de_DE" ) << QString("1,234e-10" ) << true << 1.234e-10; |
851 | QTest::newRow(dataTag: "de_DE 1,234E10" ) << QString("de_DE" ) << QString("1,234E10" ) << true << 1.234e10; |
852 | QTest::newRow(dataTag: "de_DE ,1" ) << QString("de_DE" ) << QString(",1" ) << true << 0.1; |
853 | QTest::newRow(dataTag: "de_DE -,1" ) << QString("de_DE" ) << QString("-,1" ) << true << -0.1; |
854 | QTest::newRow(dataTag: "de_DE 1," ) << QString("de_DE" ) << QString("1," ) << true << 1.0; |
855 | QTest::newRow(dataTag: "de_DE 1,E10" ) << QString("de_DE" ) << QString("1,E10" ) << true << 1.0e10; |
856 | |
857 | QTest::newRow(dataTag: "de_DE empty" ) << QString("de_DE" ) << QString("" ) << false << 0.0; |
858 | QTest::newRow(dataTag: "de_DE null" ) << QString("de_DE" ) << QString() << false << 0.0; |
859 | QTest::newRow(dataTag: "de_DE ." ) << QString("de_DE" ) << QString("." ) << false << 0.0; |
860 | QTest::newRow(dataTag: "de_DE 1e" ) << QString("de_DE" ) << QString("1e" ) << false << 0.0; |
861 | QTest::newRow(dataTag: "de_DE 1e1.0" ) << QString("de_DE" ) << QString("1e1.0" ) << false << 0.0; |
862 | QTest::newRow(dataTag: "de_DE 1e+" ) << QString("de_DE" ) << QString("1e+" ) << false << 0.0; |
863 | QTest::newRow(dataTag: "de_DE 1e-" ) << QString("de_DE" ) << QString("1e-" ) << false << 0.0; |
864 | |
865 | QTest::newRow(dataTag: "C 9,876543" ) << QString("C" ) << QString("9,876543" ) << false << 0.0; |
866 | QTest::newRow(dataTag: "C 9,876543.2" ) << QString("C" ) << QString("9,876543.2" ) << false << 0.0; |
867 | QTest::newRow(dataTag: "C 9,876543e-2" ) << QString("C" ) << QString("9,876543e-2" ) << false << 0.0; |
868 | QTest::newRow(dataTag: "C 9,876543.0e-2" ) << QString("C" ) << QString("9,876543.0e-2" ) << false << 0.0; |
869 | |
870 | QTest::newRow(dataTag: "de_DE 9.876543" ) << QString("de_DE" ) << QString("9876.543" ) << false << 0.0; |
871 | QTest::newRow(dataTag: "de_DE 9.876543,2" ) << QString("de_DE" ) << QString("9.876543,2" ) << false << 0.0; |
872 | QTest::newRow(dataTag: "de_DE 9.876543e-2" ) << QString("de_DE" ) << QString("9.876543e-2" ) << false << 0.0; |
873 | QTest::newRow(dataTag: "de_DE 9.876543,0e-2" ) << QString("de_DE" ) << QString("9.876543,0e-2" ) << false << 0.0; |
874 | QTest::newRow(dataTag: "de_DE 9.876543e--2" ) << QString("de_DE" ) << QString("9.876543e" )+QChar(8722)+QString("2" ) << false << 0.0; |
875 | QTest::newRow(dataTag: "de_DE 9.876543,0e--2" ) << QString("de_DE" ) << QString("9.876543,0e" )+QChar(8722)+QString("2" ) << false << 0.0; |
876 | } |
877 | |
878 | void tst_QLocale::stringToDouble_data() |
879 | { |
880 | toReal_data(); |
881 | if (std::numeric_limits<double>::has_infinity) { |
882 | double huge = std::numeric_limits<double>::infinity(); |
883 | QTest::newRow(dataTag: "C inf" ) << QString("C" ) << QString("inf" ) << true << huge; |
884 | QTest::newRow(dataTag: "C +inf" ) << QString("C" ) << QString("+inf" ) << true << +huge; |
885 | QTest::newRow(dataTag: "C -inf" ) << QString("C" ) << QString("-inf" ) << true << -huge; |
886 | // Overflow: |
887 | QTest::newRow(dataTag: "C huge" ) << QString("C" ) << QString("2e308" ) << false << huge; |
888 | QTest::newRow(dataTag: "C -huge" ) << QString("C" ) << QString("-2e308" ) << false << -huge; |
889 | } |
890 | if (std::numeric_limits<double>::has_quiet_NaN) |
891 | QTest::newRow(dataTag: "C qnan" ) << QString("C" ) << QString("NaN" ) << true << std::numeric_limits<double>::quiet_NaN(); |
892 | |
893 | // In range (but outside float's range): |
894 | QTest::newRow(dataTag: "C big" ) << QString("C" ) << QString("3.5e38" ) << true << 3.5e38; |
895 | QTest::newRow(dataTag: "C -big" ) << QString("C" ) << QString("-3.5e38" ) << true << -3.5e38; |
896 | QTest::newRow(dataTag: "C small" ) << QString("C" ) << QString("1e-45" ) << true << 1e-45; |
897 | QTest::newRow(dataTag: "C -small" ) << QString("C" ) << QString("-1e-45" ) << true << -1e-45; |
898 | |
899 | // Underflow: |
900 | QTest::newRow(dataTag: "C tiny" ) << QString("C" ) << QString("2e-324" ) << false << 0.; |
901 | QTest::newRow(dataTag: "C -tiny" ) << QString("C" ) << QString("-2e-324" ) << false << 0.; |
902 | } |
903 | |
904 | void tst_QLocale::stringToDouble() |
905 | { |
906 | #define MY_DOUBLE_EPSILON (2.22045e-16) // 1/2^{52}; double has a 53-bit mantissa |
907 | |
908 | QFETCH(QString, locale_name); |
909 | QFETCH(QString, num_str); |
910 | QFETCH(bool, good); |
911 | QFETCH(double, num); |
912 | QStringRef num_strRef = num_str.leftRef(n: -1); |
913 | |
914 | QLocale locale(locale_name); |
915 | QCOMPARE(locale.name(), locale_name); |
916 | |
917 | bool ok; |
918 | double d = locale.toDouble(s: num_str, ok: &ok); |
919 | QCOMPARE(ok, good); |
920 | |
921 | { |
922 | // Make sure result is independent of locale: |
923 | TransientLocale ignoreme(LC_ALL, "ar_SA" ); |
924 | QCOMPARE(locale.toDouble(num_str, &ok), d); |
925 | QCOMPARE(ok, good); |
926 | } |
927 | |
928 | if (ok || std::isinf(x: num)) { |
929 | // First use fuzzy-compare, then a more precise check: |
930 | QCOMPARE(d, num); |
931 | if (std::isfinite(x: num)) { |
932 | double diff = d > num ? d - num : num - d; |
933 | QVERIFY(diff <= MY_DOUBLE_EPSILON); |
934 | } |
935 | } |
936 | |
937 | d = locale.toDouble(s: num_strRef, ok: &ok); |
938 | QCOMPARE(ok, good); |
939 | |
940 | if (ok || std::isinf(x: num)) { |
941 | QCOMPARE(d, num); |
942 | if (std::isfinite(x: num)) { |
943 | double diff = d > num ? d - num : num - d; |
944 | QVERIFY(diff <= MY_DOUBLE_EPSILON); |
945 | } |
946 | } |
947 | #undef MY_DOUBLE_EPSILON |
948 | } |
949 | |
950 | void tst_QLocale::stringToFloat_data() |
951 | { |
952 | using Bounds = std::numeric_limits<float>; |
953 | toReal_data(); |
954 | const QString C(QStringLiteral("C" )); |
955 | if (Bounds::has_infinity) { |
956 | double huge = Bounds::infinity(); |
957 | QTest::newRow(dataTag: "C inf" ) << C << QString("inf" ) << true << huge; |
958 | QTest::newRow(dataTag: "C +inf" ) << C << QString("+inf" ) << true << +huge; |
959 | QTest::newRow(dataTag: "C -inf" ) << C << QString("-inf" ) << true << -huge; |
960 | // Overflow float, but not double: |
961 | QTest::newRow(dataTag: "C big" ) << C << QString("3.5e38" ) << false << huge; |
962 | QTest::newRow(dataTag: "C -big" ) << C << QString("-3.5e38" ) << false << -huge; |
963 | // Overflow double, too: |
964 | QTest::newRow(dataTag: "C huge" ) << C << QString("2e308" ) << false << huge; |
965 | QTest::newRow(dataTag: "C -huge" ) << C << QString("-2e308" ) << false << -huge; |
966 | } |
967 | if (Bounds::has_quiet_NaN) |
968 | QTest::newRow(dataTag: "C qnan" ) << C << QString("NaN" ) << true << double(Bounds::quiet_NaN()); |
969 | |
970 | // Minimal float: shouldn't underflow |
971 | QTest::newRow(dataTag: "C float min" ) |
972 | << C << QLocale::c().toString(i: Bounds::denorm_min()) << true << double(Bounds::denorm_min()); |
973 | QTest::newRow(dataTag: "C float -min" ) |
974 | << C << QLocale::c().toString(i: -Bounds::denorm_min()) << true << -double(Bounds::denorm_min()); |
975 | |
976 | // Underflow float, but not double: |
977 | QTest::newRow(dataTag: "C small" ) << C << QString("7e-46" ) << false << 0.; |
978 | QTest::newRow(dataTag: "C -small" ) << C << QString("-7e-46" ) << false << 0.; |
979 | using Double = std::numeric_limits<double>; |
980 | QTest::newRow(dataTag: "C double min" ) |
981 | << C << QLocale::c().toString(i: Double::denorm_min()) << false << 0.0; |
982 | QTest::newRow(dataTag: "C double -min" ) |
983 | << C << QLocale::c().toString(i: -Double::denorm_min()) << false << 0.0; |
984 | |
985 | // Underflow double, too: |
986 | QTest::newRow(dataTag: "C tiny" ) << C << QString("2e-324" ) << false << 0.; |
987 | QTest::newRow(dataTag: "C -tiny" ) << C << QString("-2e-324" ) << false << 0.; |
988 | } |
989 | |
990 | void tst_QLocale::stringToFloat() |
991 | { |
992 | #define MY_FLOAT_EPSILON (2.384e-7) // 1/2^{22}; float has a 23-bit mantissa |
993 | |
994 | QFETCH(QString, locale_name); |
995 | QFETCH(QString, num_str); |
996 | QFETCH(bool, good); |
997 | QFETCH(double, num); |
998 | QStringRef num_strRef = num_str.leftRef(n: -1); |
999 | float fnum = num; |
1000 | |
1001 | QLocale locale(locale_name); |
1002 | QCOMPARE(locale.name(), locale_name); |
1003 | |
1004 | bool ok; |
1005 | float f = locale.toFloat(s: num_str, ok: &ok); |
1006 | QCOMPARE(ok, good); |
1007 | |
1008 | { |
1009 | // Make sure result is independent of locale: |
1010 | TransientLocale ignoreme(LC_ALL, "ar_SA" ); |
1011 | QCOMPARE(locale.toFloat(num_str, &ok), f); |
1012 | QCOMPARE(ok, good); |
1013 | } |
1014 | |
1015 | if (ok || std::isinf(x: fnum)) { |
1016 | // First use fuzzy-compare, then a more precise check: |
1017 | QCOMPARE(f, fnum); |
1018 | if (std::isfinite(x: fnum)) { |
1019 | float diff = f > fnum ? f - fnum : fnum - f; |
1020 | QVERIFY(diff <= MY_FLOAT_EPSILON); |
1021 | } |
1022 | } |
1023 | |
1024 | f = locale.toFloat(s: num_strRef, ok: &ok); |
1025 | QCOMPARE(ok, good); |
1026 | |
1027 | if (ok || std::isinf(x: fnum)) { |
1028 | QCOMPARE(f, fnum); |
1029 | if (std::isfinite(x: fnum)) { |
1030 | float diff = f > fnum ? f - fnum : fnum - f; |
1031 | QVERIFY(diff <= MY_FLOAT_EPSILON); |
1032 | } |
1033 | } |
1034 | #undef MY_FLOAT_EPSILON |
1035 | } |
1036 | |
1037 | void tst_QLocale::doubleToString_data() |
1038 | { |
1039 | QTest::addColumn<QString>(name: "locale_name" ); |
1040 | QTest::addColumn<QString>(name: "num_str" ); |
1041 | QTest::addColumn<double>(name: "num" ); |
1042 | QTest::addColumn<char>(name: "mode" ); |
1043 | QTest::addColumn<int>(name: "precision" ); |
1044 | |
1045 | int shortest = QLocale::FloatingPointShortest; |
1046 | |
1047 | QTest::newRow(dataTag: "C 3.4 f 5" ) << QString("C" ) << QString("3.40000" ) << 3.4 << 'f' << 5; |
1048 | QTest::newRow(dataTag: "C 3.4 f 0" ) << QString("C" ) << QString("3" ) << 3.4 << 'f' << 0; |
1049 | QTest::newRow(dataTag: "C 3.4 e 5" ) << QString("C" ) << QString("3.40000e+00" ) << 3.4 << 'e' << 5; |
1050 | QTest::newRow(dataTag: "C 3.4 e 0" ) << QString("C" ) << QString("3e+00" ) << 3.4 << 'e' << 0; |
1051 | QTest::newRow(dataTag: "C 3.4 g 5" ) << QString("C" ) << QString("3.4" ) << 3.4 << 'g' << 5; |
1052 | QTest::newRow(dataTag: "C 3.4 g 1" ) << QString("C" ) << QString("3" ) << 3.4 << 'g' << 1; |
1053 | |
1054 | QTest::newRow(dataTag: "C 3.4 f 1" ) << QString("C" ) << QString("3.4" ) << 3.4 << 'f' << 1; |
1055 | QTest::newRow(dataTag: "C 3.4 f -" ) << QString("C" ) << QString("3.4" ) << 3.4 << 'f' << shortest; |
1056 | QTest::newRow(dataTag: "C 3.4 e 1" ) << QString("C" ) << QString("3.4e+00" ) << 3.4 << 'e' << 1; |
1057 | QTest::newRow(dataTag: "C 3.4 e -" ) << QString("C" ) << QString("3.4e+00" ) << 3.4 << 'e' << shortest; |
1058 | QTest::newRow(dataTag: "C 3.4 g 2" ) << QString("C" ) << QString("3.4" ) << 3.4 << 'g' << 2; |
1059 | QTest::newRow(dataTag: "C 3.4 g -" ) << QString("C" ) << QString("3.4" ) << 3.4 << 'g' << shortest; |
1060 | |
1061 | QTest::newRow(dataTag: "de_DE 3,4 f 1" ) << QString("de_DE" ) << QString("3,4" ) << 3.4 << 'f' << 1; |
1062 | QTest::newRow(dataTag: "de_DE 3,4 f -" ) << QString("de_DE" ) << QString("3,4" ) << 3.4 << 'f' << shortest; |
1063 | QTest::newRow(dataTag: "de_DE 3,4 e 1" ) << QString("de_DE" ) << QString("3,4e+00" ) << 3.4 << 'e' << 1; |
1064 | QTest::newRow(dataTag: "de_DE 3,4 e -" ) << QString("de_DE" ) << QString("3,4e+00" ) << 3.4 << 'e' << shortest; |
1065 | QTest::newRow(dataTag: "de_DE 3,4 g 2" ) << QString("de_DE" ) << QString("3,4" ) << 3.4 << 'g' << 2; |
1066 | QTest::newRow(dataTag: "de_DE 3,4 g -" ) << QString("de_DE" ) << QString("3,4" ) << 3.4 << 'g' << shortest; |
1067 | |
1068 | QTest::newRow(dataTag: "C 0.035003945 f 12" ) << QString("C" ) << QString("0.035003945000" ) << 0.035003945 << 'f' << 12; |
1069 | QTest::newRow(dataTag: "C 0.035003945 f 6" ) << QString("C" ) << QString("0.035004" ) << 0.035003945 << 'f' << 6; |
1070 | QTest::newRow(dataTag: "C 0.035003945 e 10" ) << QString("C" ) << QString("3.5003945000e-02" ) << 0.035003945 << 'e' << 10; |
1071 | QTest::newRow(dataTag: "C 0.035003945 e 4" ) << QString("C" ) << QString("3.5004e-02" ) << 0.035003945 << 'e' << 4; |
1072 | QTest::newRow(dataTag: "C 0.035003945 g 11" ) << QString("C" ) << QString("0.035003945" ) << 0.035003945 << 'g' << 11; |
1073 | QTest::newRow(dataTag: "C 0.035003945 g 5" ) << QString("C" ) << QString("0.035004" ) << 0.035003945 << 'g' << 5; |
1074 | |
1075 | QTest::newRow(dataTag: "C 0.035003945 f 9" ) << QString("C" ) << QString("0.035003945" ) << 0.035003945 << 'f' << 9; |
1076 | QTest::newRow(dataTag: "C 0.035003945 f -" ) << QString("C" ) << QString("0.035003945" ) << 0.035003945 << 'f' << shortest; |
1077 | QTest::newRow(dataTag: "C 0.035003945 e 7" ) << QString("C" ) << QString("3.5003945e-02" ) << 0.035003945 << 'e' << 7; |
1078 | QTest::newRow(dataTag: "C 0.035003945 e -" ) << QString("C" ) << QString("3.5003945e-02" ) << 0.035003945 << 'e' << shortest; |
1079 | QTest::newRow(dataTag: "C 0.035003945 g 8" ) << QString("C" ) << QString("0.035003945" ) << 0.035003945 << 'g' << 8; |
1080 | QTest::newRow(dataTag: "C 0.035003945 g -" ) << QString("C" ) << QString("0.035003945" ) << 0.035003945 << 'g' << shortest; |
1081 | |
1082 | QTest::newRow(dataTag: "de_DE 0,035003945 f 9" ) << QString("de_DE" ) << QString("0,035003945" ) << 0.035003945 << 'f' << 9; |
1083 | QTest::newRow(dataTag: "de_DE 0,035003945 f -" ) << QString("de_DE" ) << QString("0,035003945" ) << 0.035003945 << 'f' << shortest; |
1084 | QTest::newRow(dataTag: "de_DE 0,035003945 e 7" ) << QString("de_DE" ) << QString("3,5003945e-02" ) << 0.035003945 << 'e' << 7; |
1085 | QTest::newRow(dataTag: "de_DE 0,035003945 e -" ) << QString("de_DE" ) << QString("3,5003945e-02" ) << 0.035003945 << 'e' << shortest; |
1086 | QTest::newRow(dataTag: "de_DE 0,035003945 g 8" ) << QString("de_DE" ) << QString("0,035003945" ) << 0.035003945 << 'g' << 8; |
1087 | QTest::newRow(dataTag: "de_DE 0,035003945 g -" ) << QString("de_DE" ) << QString("0,035003945" ) << 0.035003945 << 'g' << shortest; |
1088 | |
1089 | QTest::newRow(dataTag: "C 0.000003945 f 12" ) << QString("C" ) << QString("0.000003945000" ) << 0.000003945 << 'f' << 12; |
1090 | QTest::newRow(dataTag: "C 0.000003945 f 6" ) << QString("C" ) << QString("0.000004" ) << 0.000003945 << 'f' << 6; |
1091 | QTest::newRow(dataTag: "C 0.000003945 e 6" ) << QString("C" ) << QString("3.945000e-06" ) << 0.000003945 << 'e' << 6; |
1092 | QTest::newRow(dataTag: "C 0.000003945 e 0" ) << QString("C" ) << QString("4e-06" ) << 0.000003945 << 'e' << 0; |
1093 | QTest::newRow(dataTag: "C 0.000003945 g 7" ) << QString("C" ) << QString("3.945e-06" ) << 0.000003945 << 'g' << 7; |
1094 | QTest::newRow(dataTag: "C 0.000003945 g 1" ) << QString("C" ) << QString("4e-06" ) << 0.000003945 << 'g' << 1; |
1095 | |
1096 | QTest::newRow(dataTag: "C 0.000003945 f 9" ) << QString("C" ) << QString("0.000003945" ) << 0.000003945 << 'f' << 9; |
1097 | QTest::newRow(dataTag: "C 0.000003945 f -" ) << QString("C" ) << QString("0.000003945" ) << 0.000003945 << 'f' << shortest; |
1098 | QTest::newRow(dataTag: "C 0.000003945 e 3" ) << QString("C" ) << QString("3.945e-06" ) << 0.000003945 << 'e' << 3; |
1099 | QTest::newRow(dataTag: "C 0.000003945 e -" ) << QString("C" ) << QString("3.945e-06" ) << 0.000003945 << 'e' << shortest; |
1100 | QTest::newRow(dataTag: "C 0.000003945 g 4" ) << QString("C" ) << QString("3.945e-06" ) << 0.000003945 << 'g' << 4; |
1101 | QTest::newRow(dataTag: "C 0.000003945 g -" ) << QString("C" ) << QString("3.945e-06" ) << 0.000003945 << 'g' << shortest; |
1102 | |
1103 | QTest::newRow(dataTag: "de_DE 0,000003945 f 9" ) << QString("de_DE" ) << QString("0,000003945" ) << 0.000003945 << 'f' << 9; |
1104 | QTest::newRow(dataTag: "de_DE 0,000003945 f -" ) << QString("de_DE" ) << QString("0,000003945" ) << 0.000003945 << 'f' << shortest; |
1105 | QTest::newRow(dataTag: "de_DE 0,000003945 e 3" ) << QString("de_DE" ) << QString("3,945e-06" ) << 0.000003945 << 'e' << 3; |
1106 | QTest::newRow(dataTag: "de_DE 0,000003945 e -" ) << QString("de_DE" ) << QString("3,945e-06" ) << 0.000003945 << 'e' << shortest; |
1107 | QTest::newRow(dataTag: "de_DE 0,000003945 g 4" ) << QString("de_DE" ) << QString("3,945e-06" ) << 0.000003945 << 'g' << 4; |
1108 | QTest::newRow(dataTag: "de_DE 0,000003945 g -" ) << QString("de_DE" ) << QString("3,945e-06" ) << 0.000003945 << 'g' << shortest; |
1109 | |
1110 | QTest::newRow(dataTag: "C 12456789012 f 3" ) << QString("C" ) << QString("12456789012.000" ) << 12456789012.0 << 'f' << 3; |
1111 | QTest::newRow(dataTag: "C 12456789012 e 13" ) << QString("C" ) << QString("1.2456789012000e+10" ) << 12456789012.0 << 'e' << 13; |
1112 | QTest::newRow(dataTag: "C 12456789012 e 7" ) << QString("C" ) << QString("1.2456789e+10" ) << 12456789012.0 << 'e' << 7; |
1113 | QTest::newRow(dataTag: "C 12456789012 g 14" ) << QString("C" ) << QString("12456789012" ) << 12456789012.0 << 'g' << 14; |
1114 | QTest::newRow(dataTag: "C 12456789012 g 8" ) << QString("C" ) << QString("1.2456789e+10" ) << 12456789012.0 << 'g' << 8; |
1115 | |
1116 | QTest::newRow(dataTag: "C 12456789012 f 0" ) << QString("C" ) << QString("12456789012" ) << 12456789012.0 << 'f' << 0; |
1117 | QTest::newRow(dataTag: "C 12456789012 f -" ) << QString("C" ) << QString("12456789012" ) << 12456789012.0 << 'f' << shortest; |
1118 | QTest::newRow(dataTag: "C 12456789012 e 10" ) << QString("C" ) << QString("1.2456789012e+10" ) << 12456789012.0 << 'e' << 10; |
1119 | QTest::newRow(dataTag: "C 12456789012 e -" ) << QString("C" ) << QString("1.2456789012e+10" ) << 12456789012.0 << 'e' << shortest; |
1120 | QTest::newRow(dataTag: "C 12456789012 g 11" ) << QString("C" ) << QString("12456789012" ) << 12456789012.0 << 'g' << 11; |
1121 | QTest::newRow(dataTag: "C 12456789012 g -" ) << QString("C" ) << QString("12456789012" ) << 12456789012.0 << 'g' << shortest; |
1122 | |
1123 | QTest::newRow(dataTag: "de_DE 12456789012 f 0" ) << QString("de_DE" ) << QString("12.456.789.012" ) << 12456789012.0 << 'f' << 0; |
1124 | QTest::newRow(dataTag: "de_DE 12456789012 f -" ) << QString("de_DE" ) << QString("12.456.789.012" ) << 12456789012.0 << 'f' << shortest; |
1125 | QTest::newRow(dataTag: "de_DE 12456789012 e 10" ) << QString("de_DE" ) << QString("1,2456789012e+10" ) << 12456789012.0 << 'e' << 10; |
1126 | QTest::newRow(dataTag: "de_DE 12456789012 e -" ) << QString("de_DE" ) << QString("1,2456789012e+10" ) << 12456789012.0 << 'e' << shortest; |
1127 | QTest::newRow(dataTag: "de_DE 12456789012 g 11" ) << QString("de_DE" ) << QString("12.456.789.012" ) << 12456789012.0 << 'g' << 11; |
1128 | QTest::newRow(dataTag: "de_DE 12456789012 g -" ) << QString("de_DE" ) << QString("12.456.789.012" ) << 12456789012.0 << 'g' << shortest; |
1129 | } |
1130 | |
1131 | void tst_QLocale::doubleToString() |
1132 | { |
1133 | QFETCH(QString, locale_name); |
1134 | QFETCH(QString, num_str); |
1135 | QFETCH(double, num); |
1136 | QFETCH(char, mode); |
1137 | QFETCH(int, precision); |
1138 | |
1139 | #ifdef QT_NO_DOUBLECONVERSION |
1140 | if (precision == QLocale::FloatingPointShortest) |
1141 | QSKIP("'Shortest' double conversion is not that short without libdouble-conversion" ); |
1142 | #endif |
1143 | |
1144 | const QLocale locale(locale_name); |
1145 | QCOMPARE(locale.toString(num, mode, precision), num_str); |
1146 | |
1147 | TransientLocale ignoreme(LC_ALL, "de_DE" ); |
1148 | QCOMPARE(locale.toString(num, mode, precision), num_str); |
1149 | } |
1150 | |
1151 | void tst_QLocale::strtod_data() |
1152 | { |
1153 | QTest::addColumn<QString>(name: "num_str" ); |
1154 | QTest::addColumn<double>(name: "num" ); |
1155 | QTest::addColumn<int>(name: "processed" ); |
1156 | QTest::addColumn<bool>(name: "ok" ); |
1157 | |
1158 | // plain numbers, success |
1159 | QTest::newRow(dataTag: "0" ) << QString("0" ) << 0.0 << 1 << true; |
1160 | QTest::newRow(dataTag: "0." ) << QString("0." ) << 0.0 << 2 << true; |
1161 | QTest::newRow(dataTag: "0.0" ) << QString("0.0" ) << 0.0 << 3 << true; |
1162 | QTest::newRow(dataTag: "0e+0" ) << QString("0e+0" ) << 0.0 << 4 << true; |
1163 | QTest::newRow(dataTag: "0e-0" ) << QString("0e-0" ) << 0.0 << 4 << true; |
1164 | QTest::newRow(dataTag: "0e+1" ) << QString("0e+1" ) << 0.0 << 4 << true; |
1165 | QTest::newRow(dataTag: "0e-1" ) << QString("0e-1" ) << 0.0 << 4 << true; |
1166 | QTest::newRow(dataTag: "0E+0" ) << QString("0E+0" ) << 0.0 << 4 << true; |
1167 | QTest::newRow(dataTag: "0E-0" ) << QString("0E-0" ) << 0.0 << 4 << true; |
1168 | QTest::newRow(dataTag: "0E+1" ) << QString("0E+1" ) << 0.0 << 4 << true; |
1169 | QTest::newRow(dataTag: "0E-1" ) << QString("0E-1" ) << 0.0 << 4 << true; |
1170 | QTest::newRow(dataTag: "3.4" ) << QString("3.4" ) << 3.4 << 3 << true; |
1171 | QTest::newRow(dataTag: "0.035003945" ) << QString("0.035003945" ) << 0.035003945 << 11 << true; |
1172 | QTest::newRow(dataTag: "3.5003945e-2" ) << QString("3.5003945e-2" ) << 0.035003945 << 12 << true; |
1173 | QTest::newRow(dataTag: "0.000003945" ) << QString("0.000003945" ) << 0.000003945 << 11 << true; |
1174 | QTest::newRow(dataTag: "3.945e-6" ) << QString("3.945e-6" ) << 0.000003945 << 8 << true; |
1175 | QTest::newRow(dataTag: "12456789012" ) << QString("12456789012" ) << 12456789012.0 << 11 << true; |
1176 | QTest::newRow(dataTag: "1.2456789012e10" ) << QString("1.2456789012e10" ) << 12456789012.0 << 15 << true; |
1177 | |
1178 | // starts with junk, fails |
1179 | QTest::newRow(dataTag: "a0" ) << QString("a0" ) << 0.0 << 0 << false; |
1180 | QTest::newRow(dataTag: "a0." ) << QString("a0." ) << 0.0 << 0 << false; |
1181 | QTest::newRow(dataTag: "a0.0" ) << QString("a0.0" ) << 0.0 << 0 << false; |
1182 | QTest::newRow(dataTag: "a3.4" ) << QString("a3.4" ) << 0.0 << 0 << false; |
1183 | QTest::newRow(dataTag: "b0.035003945" ) << QString("b0.035003945" ) << 0.0 << 0 << false; |
1184 | QTest::newRow(dataTag: "c3.5003945e-2" ) << QString("c3.5003945e-2" ) << 0.0 << 0 << false; |
1185 | QTest::newRow(dataTag: "d0.000003945" ) << QString("d0.000003945" ) << 0.0 << 0 << false; |
1186 | QTest::newRow(dataTag: "e3.945e-6" ) << QString("e3.945e-6" ) << 0.0 << 0 << false; |
1187 | QTest::newRow(dataTag: "f12456789012" ) << QString("f12456789012" ) << 0.0 << 0 << false; |
1188 | QTest::newRow(dataTag: "g1.2456789012e10" ) << QString("g1.2456789012e10" ) << 0.0 << 0 << false; |
1189 | |
1190 | // ends with junk, success |
1191 | QTest::newRow(dataTag: "0a" ) << QString("0a" ) << 0.0 << 1 << true; |
1192 | QTest::newRow(dataTag: "0.a" ) << QString("0.a" ) << 0.0 << 2 << true; |
1193 | QTest::newRow(dataTag: "0.0a" ) << QString("0.0a" ) << 0.0 << 3 << true; |
1194 | QTest::newRow(dataTag: "0e+0a" ) << QString("0e+0a" ) << 0.0 << 4 << true; |
1195 | QTest::newRow(dataTag: "0e-0a" ) << QString("0e-0a" ) << 0.0 << 4 << true; |
1196 | QTest::newRow(dataTag: "0e+1a" ) << QString("0e+1a" ) << 0.0 << 4 << true; |
1197 | QTest::newRow(dataTag: "0e-1a" ) << QString("0e-1a" ) << 0.0 << 4 << true; |
1198 | QTest::newRow(dataTag: "0E+0a" ) << QString("0E+0a" ) << 0.0 << 4 << true; |
1199 | QTest::newRow(dataTag: "0E-0a" ) << QString("0E-0a" ) << 0.0 << 4 << true; |
1200 | QTest::newRow(dataTag: "0E+1a" ) << QString("0E+1a" ) << 0.0 << 4 << true; |
1201 | QTest::newRow(dataTag: "0E-1a" ) << QString("0E-1a" ) << 0.0 << 4 << true; |
1202 | QTest::newRow(dataTag: "0.035003945b" ) << QString("0.035003945b" ) << 0.035003945 << 11 << true; |
1203 | QTest::newRow(dataTag: "3.5003945e-2c" ) << QString("3.5003945e-2c" ) << 0.035003945 << 12 << true; |
1204 | QTest::newRow(dataTag: "0.000003945d" ) << QString("0.000003945d" ) << 0.000003945 << 11 << true; |
1205 | QTest::newRow(dataTag: "3.945e-6e" ) << QString("3.945e-6e" ) << 0.000003945 << 8 << true; |
1206 | QTest::newRow(dataTag: "12456789012f" ) << QString("12456789012f" ) << 12456789012.0 << 11 << true; |
1207 | QTest::newRow(dataTag: "1.2456789012e10g" ) << QString("1.2456789012e10g" ) << 12456789012.0 << 15 << true; |
1208 | |
1209 | // "0x" prefix, success but only for the "0" before "x" |
1210 | QTest::newRow(dataTag: "0x0" ) << QString("0x0" ) << 0.0 << 1 << true; |
1211 | QTest::newRow(dataTag: "0x0." ) << QString("0x0." ) << 0.0 << 1 << true; |
1212 | QTest::newRow(dataTag: "0x0.0" ) << QString("0x0.0" ) << 0.0 << 1 << true; |
1213 | QTest::newRow(dataTag: "0x3.4" ) << QString("0x3.4" ) << 0.0 << 1 << true; |
1214 | QTest::newRow(dataTag: "0x0.035003945" ) << QString("0x0.035003945" ) << 0.0 << 1 << true; |
1215 | QTest::newRow(dataTag: "0x3.5003945e-2" ) << QString("0x3.5003945e-2" ) << 0.0 << 1 << true; |
1216 | QTest::newRow(dataTag: "0x0.000003945" ) << QString("0x0.000003945" ) << 0.0 << 1 << true; |
1217 | QTest::newRow(dataTag: "0x3.945e-6" ) << QString("0x3.945e-6" ) << 0.0 << 1 << true; |
1218 | QTest::newRow(dataTag: "0x12456789012" ) << QString("0x12456789012" ) << 0.0 << 1 << true; |
1219 | QTest::newRow(dataTag: "0x1.2456789012e10" ) << QString("0x1.2456789012e10" ) << 0.0 << 1 << true; |
1220 | |
1221 | // hexfloat is not supported (yet) |
1222 | QTest::newRow(dataTag: "0x1.921fb5p+1" ) << QString("0x1.921fb5p+1" ) << 0.0 << 1 << true; |
1223 | } |
1224 | |
1225 | void tst_QLocale::strtod() |
1226 | { |
1227 | QFETCH(QString, num_str); |
1228 | QFETCH(double, num); |
1229 | QFETCH(int, processed); |
1230 | QFETCH(bool, ok); |
1231 | |
1232 | QByteArray numData = num_str.toLatin1(); |
1233 | const char *end = 0; |
1234 | bool actualOk = false; |
1235 | double result = qstrtod(s00: numData.constData(), se: &end, ok: &actualOk); |
1236 | |
1237 | QCOMPARE(result, num); |
1238 | QCOMPARE(actualOk, ok); |
1239 | QCOMPARE(static_cast<int>(end - numData.constData()), processed); |
1240 | |
1241 | // make sure neither QByteArray, QString or QLocale also work |
1242 | // (but they don't support incomplete parsing) |
1243 | if (processed == num_str.size() || processed == 0) { |
1244 | actualOk = false; |
1245 | QCOMPARE(num_str.toDouble(&actualOk), num); |
1246 | QCOMPARE(actualOk, ok); |
1247 | |
1248 | actualOk = false; |
1249 | QCOMPARE(numData.toDouble(&actualOk), num); |
1250 | QCOMPARE(actualOk, ok); |
1251 | |
1252 | actualOk = false; |
1253 | QCOMPARE(QLocale::c().toDouble(num_str, &actualOk), num); |
1254 | QCOMPARE(actualOk, ok); |
1255 | } |
1256 | |
1257 | // and QStringRef, but we can limit the length without allocating memory |
1258 | QStringRef num_strref(&num_str, 0, processed); |
1259 | actualOk = false; |
1260 | QCOMPARE(QLocale::c().toDouble(num_strref, &actualOk), num); |
1261 | QCOMPARE(actualOk, ok); |
1262 | } |
1263 | |
1264 | void tst_QLocale::long_long_conversion_data() |
1265 | { |
1266 | QTest::addColumn<QString>(name: "locale_name" ); |
1267 | QTest::addColumn<QString>(name: "num_str" ); |
1268 | QTest::addColumn<bool>(name: "good" ); |
1269 | QTest::addColumn<qlonglong>(name: "num" ); |
1270 | |
1271 | QTest::newRow(dataTag: "C null" ) << QString("C" ) << QString() << false << (qlonglong) 0; |
1272 | QTest::newRow(dataTag: "C empty" ) << QString("C" ) << QString("" ) << false << (qlonglong) 0; |
1273 | QTest::newRow(dataTag: "C 1" ) << QString("C" ) << "1" << true << (qlonglong) 1; |
1274 | QTest::newRow(dataTag: "C 1," ) << QString("C" ) << "1," << false << (qlonglong) 0; |
1275 | QTest::newRow(dataTag: "C 1,2" ) << QString("C" ) << "1,2" << false << (qlonglong) 0; |
1276 | QTest::newRow(dataTag: "C 1,23" ) << QString("C" ) << "1,23" << false << (qlonglong) 0; |
1277 | QTest::newRow(dataTag: "C 1,234" ) << QString("C" ) << "1,234" << true << (qlonglong) 1234; |
1278 | QTest::newRow(dataTag: "C 1234567" ) << QString("C" ) << "1234567" << true << (qlonglong) 1234567; |
1279 | QTest::newRow(dataTag: "C 1,234567" ) << QString("C" ) << "1,234567" << false << (qlonglong) 0; |
1280 | QTest::newRow(dataTag: "C 12,34567" ) << QString("C" ) << "12,34567" << false << (qlonglong) 0; |
1281 | QTest::newRow(dataTag: "C 123,4567" ) << QString("C" ) << "123,4567" << false << (qlonglong) 0; |
1282 | QTest::newRow(dataTag: "C 1234,567" ) << QString("C" ) << "1234,567" << false << (qlonglong) 0; |
1283 | QTest::newRow(dataTag: "C 12345,67" ) << QString("C" ) << "12345,67" << false << (qlonglong) 0; |
1284 | QTest::newRow(dataTag: "C 123456,7" ) << QString("C" ) << "123456,7" << false << (qlonglong) 0; |
1285 | QTest::newRow(dataTag: "C 1,234,567" ) << QString("C" ) << "1,234,567" << true << (qlonglong) 1234567; |
1286 | |
1287 | QTest::newRow(dataTag: "de_DE 1" ) << QString("de_DE" ) << "1" << true << (qlonglong) 1; |
1288 | QTest::newRow(dataTag: "de_DE 1." ) << QString("de_DE" ) << "1." << false << (qlonglong) 0; |
1289 | QTest::newRow(dataTag: "de_DE 1.2" ) << QString("de_DE" ) << "1.2" << false << (qlonglong) 0; |
1290 | QTest::newRow(dataTag: "de_DE 1.23" ) << QString("de_DE" ) << "1.23" << false << (qlonglong) 0; |
1291 | QTest::newRow(dataTag: "de_DE 1.234" ) << QString("de_DE" ) << "1.234" << true << (qlonglong) 1234; |
1292 | QTest::newRow(dataTag: "de_DE 1234567" ) << QString("de_DE" ) << "1234567" << true << (qlonglong) 1234567; |
1293 | QTest::newRow(dataTag: "de_DE 1.234567" ) << QString("de_DE" ) << "1.234567" << false << (qlonglong) 0; |
1294 | QTest::newRow(dataTag: "de_DE 12.34567" ) << QString("de_DE" ) << "12.34567" << false << (qlonglong) 0; |
1295 | QTest::newRow(dataTag: "de_DE 123.4567" ) << QString("de_DE" ) << "123.4567" << false << (qlonglong) 0; |
1296 | QTest::newRow(dataTag: "de_DE 1234.567" ) << QString("de_DE" ) << "1234.567" << false << (qlonglong) 0; |
1297 | QTest::newRow(dataTag: "de_DE 12345.67" ) << QString("de_DE" ) << "12345.67" << false << (qlonglong) 0; |
1298 | QTest::newRow(dataTag: "de_DE 123456.7" ) << QString("de_DE" ) << "123456.7" << false << (qlonglong) 0; |
1299 | QTest::newRow(dataTag: "de_DE 1.234.567" ) << QString("de_DE" ) << "1.234.567" << true << (qlonglong) 1234567; |
1300 | QTest::newRow(dataTag: "de_DE 1.234.567 ldspcs" ) << QString("de_DE" ) << " 1.234.567" << true << (qlonglong) 1234567; |
1301 | QTest::newRow(dataTag: "de_DE 1.234.567 trspcs" ) << QString("de_DE" ) << "1.234.567 " << true << (qlonglong) 1234567; |
1302 | QTest::newRow(dataTag: "de_DE 1.234.567 ldtrspcs" ) << QString("de_DE" ) << " 1.234.567 " << true << (qlonglong) 1234567; |
1303 | |
1304 | // test that space is also accepted whenever QLocale::groupSeparator() == 0xa0 (which looks like space). |
1305 | QTest::newRow(dataTag: "nb_NO 123 groupsep" ) << QString("nb_NO" ) << QString("1" )+QChar(0xa0)+QString("234" ) << true << (qlonglong) 1234; |
1306 | QTest::newRow(dataTag: "nb_NO 123 groupsep_space" ) << QString("nb_NO" ) << QString("1" )+QChar(0x20)+QString("234" ) << true << (qlonglong) 1234; |
1307 | |
1308 | QTest::newRow(dataTag: "nb_NO 123 ldspcs" ) << QString("nb_NO" ) << " 123" << true << (qlonglong) 123; |
1309 | QTest::newRow(dataTag: "nb_NO 123 trspcs" ) << QString("nb_NO" ) << "123 " << true << (qlonglong) 123; |
1310 | QTest::newRow(dataTag: "nb_NO 123 ldtrspcs" ) << QString("nb_NO" ) << " 123 " << true << (qlonglong) 123; |
1311 | |
1312 | QTest::newRow(dataTag: "C 1234" ) << QString("C" ) << " 1234" << true << (qlonglong) 1234; |
1313 | QTest::newRow(dataTag: "C 1234 " ) << QString("C" ) << "1234 " << true << (qlonglong) 1234; |
1314 | QTest::newRow(dataTag: "C 1234 " ) << QString("C" ) << " 1234 " << true << (qlonglong) 1234; |
1315 | } |
1316 | |
1317 | void tst_QLocale::long_long_conversion() |
1318 | { |
1319 | QFETCH(QString, locale_name); |
1320 | QFETCH(QString, num_str); |
1321 | QFETCH(bool, good); |
1322 | QFETCH(qlonglong, num); |
1323 | QStringRef num_strRef = num_str.leftRef(n: -1); |
1324 | |
1325 | QLocale locale(locale_name); |
1326 | QCOMPARE(locale.name(), locale_name); |
1327 | |
1328 | bool ok; |
1329 | qlonglong l = locale.toLongLong(s: num_str, ok: &ok); |
1330 | QCOMPARE(ok, good); |
1331 | |
1332 | if (ok) |
1333 | QCOMPARE(l, num); |
1334 | |
1335 | l = locale.toLongLong(s: num_strRef, ok: &ok); |
1336 | QCOMPARE(ok, good); |
1337 | |
1338 | if (ok) |
1339 | QCOMPARE(l, num); |
1340 | } |
1341 | |
1342 | void tst_QLocale::() |
1343 | { |
1344 | QLocale l(QLocale::C); |
1345 | l.setNumberOptions({ }); |
1346 | QCOMPARE(l.toString((qlonglong)1), QString("1" )); |
1347 | QCOMPARE(l.toString((qlonglong)12), QString("12" )); |
1348 | QCOMPARE(l.toString((qlonglong)123), QString("123" )); |
1349 | QCOMPARE(l.toString((qlonglong)1234), QString("1,234" )); |
1350 | QCOMPARE(l.toString((qlonglong)12345), QString("12,345" )); |
1351 | QCOMPARE(l.toString((qlonglong)-1), QString("-1" )); |
1352 | QCOMPARE(l.toString((qlonglong)-12), QString("-12" )); |
1353 | QCOMPARE(l.toString((qlonglong)-123), QString("-123" )); |
1354 | QCOMPARE(l.toString((qlonglong)-1234), QString("-1,234" )); |
1355 | QCOMPARE(l.toString((qlonglong)-12345), QString("-12,345" )); |
1356 | QCOMPARE(l.toString((qulonglong)1), QString("1" )); |
1357 | QCOMPARE(l.toString((qulonglong)12), QString("12" )); |
1358 | QCOMPARE(l.toString((qulonglong)123), QString("123" )); |
1359 | QCOMPARE(l.toString((qulonglong)1234), QString("1,234" )); |
1360 | QCOMPARE(l.toString((qulonglong)12345), QString("12,345" )); |
1361 | } |
1362 | |
1363 | void tst_QLocale::testInfAndNan() |
1364 | { |
1365 | double neginf = log(x: 0.0); |
1366 | double nan = sqrt(x: -1.0); |
1367 | |
1368 | #ifdef Q_OS_WIN |
1369 | // these cause INVALID floating point exception so we want to clear the status. |
1370 | _clear87(); |
1371 | #endif |
1372 | |
1373 | QVERIFY(qIsInf(-neginf)); |
1374 | QVERIFY(!qIsNaN(-neginf)); |
1375 | QVERIFY(!qIsFinite(-neginf)); |
1376 | |
1377 | QVERIFY(!qIsInf(nan)); |
1378 | QVERIFY(qIsNaN(nan)); |
1379 | QVERIFY(!qIsFinite(nan)); |
1380 | |
1381 | QVERIFY(!qIsInf(1.234)); |
1382 | QVERIFY(!qIsNaN(1.234)); |
1383 | QVERIFY(qIsFinite(1.234)); |
1384 | } |
1385 | |
1386 | void tst_QLocale::fpExceptions() |
1387 | { |
1388 | #ifndef _MCW_EM |
1389 | #define _MCW_EM 0x0008001F |
1390 | #endif |
1391 | #ifndef _EM_INEXACT |
1392 | #define _EM_INEXACT 0x00000001 |
1393 | #endif |
1394 | |
1395 | // check that double-to-string conversion doesn't throw floating point exceptions when they are |
1396 | // enabled |
1397 | #ifdef Q_OS_WIN |
1398 | _clear87(); |
1399 | unsigned int oldbits = _control87(0, 0); |
1400 | _control87( 0 | _EM_INEXACT, _MCW_EM ); |
1401 | #endif |
1402 | |
1403 | #ifdef QT_USE_FENV |
1404 | fenv_t envp; |
1405 | fegetenv(envp: &envp); |
1406 | feclearexcept(FE_ALL_EXCEPT); |
1407 | feenableexcept(FE_DIVBYZERO | FE_OVERFLOW | FE_UNDERFLOW | FE_INVALID); |
1408 | #endif |
1409 | |
1410 | QString::number(1000.1245); |
1411 | QString::number(1.1); |
1412 | QString::number(0.0); |
1413 | |
1414 | QVERIFY(true); |
1415 | |
1416 | #ifdef Q_OS_WIN |
1417 | _clear87(); |
1418 | _control87(oldbits, 0xFFFFF); |
1419 | #endif |
1420 | |
1421 | #ifdef QT_USE_FENV |
1422 | fesetenv(envp: &envp); |
1423 | #endif |
1424 | } |
1425 | |
1426 | void tst_QLocale::negativeZero() |
1427 | { |
1428 | double negativeZero( 0.0 ); // Initialise to zero. |
1429 | uchar *ptr = (uchar *)&negativeZero; |
1430 | ptr[QSysInfo::ByteOrder == QSysInfo::BigEndian ? 0 : 7] = 0x80; |
1431 | QString s = QString::number(negativeZero); |
1432 | QCOMPARE(s, QString("0" )); |
1433 | } |
1434 | |
1435 | void tst_QLocale::dayOfWeek_data() |
1436 | { |
1437 | QTest::addColumn<QDate>(name: "date" ); |
1438 | QTest::addColumn<QString>(name: "shortName" ); |
1439 | QTest::addColumn<QString>(name: "longName" ); |
1440 | |
1441 | QTest::newRow(dataTag: "Sun" ) << QDate(2006, 1, 1) << "Sun" << "Sunday" ; |
1442 | QTest::newRow(dataTag: "Mon" ) << QDate(2006, 1, 2) << "Mon" << "Monday" ; |
1443 | QTest::newRow(dataTag: "Tue" ) << QDate(2006, 1, 3) << "Tue" << "Tuesday" ; |
1444 | QTest::newRow(dataTag: "Wed" ) << QDate(2006, 1, 4) << "Wed" << "Wednesday" ; |
1445 | QTest::newRow(dataTag: "Thu" ) << QDate(2006, 1, 5) << "Thu" << "Thursday" ; |
1446 | QTest::newRow(dataTag: "Fri" ) << QDate(2006, 1, 6) << "Fri" << "Friday" ; |
1447 | QTest::newRow(dataTag: "Sat" ) << QDate(2006, 1, 7) << "Sat" << "Saturday" ; |
1448 | } |
1449 | |
1450 | void tst_QLocale::dayOfWeek() |
1451 | { |
1452 | QFETCH(QDate, date); |
1453 | QFETCH(QString, shortName); |
1454 | QFETCH(QString, longName); |
1455 | |
1456 | QCOMPARE(QLocale::c().toString(date, "ddd" ), shortName); |
1457 | QCOMPARE(QLocale::c().toString(date, "dddd" ), longName); |
1458 | |
1459 | QCOMPARE(QLocale::c().toString(date, u"ddd" ), shortName); |
1460 | QCOMPARE(QLocale::c().toString(date, u"dddd" ), longName); |
1461 | } |
1462 | |
1463 | void tst_QLocale::formatDate_data() |
1464 | { |
1465 | QTest::addColumn<QDate>(name: "date" ); |
1466 | QTest::addColumn<QString>(name: "format" ); |
1467 | QTest::addColumn<QString>(name: "result" ); |
1468 | |
1469 | QTest::newRow(dataTag: "1" ) << QDate(1974, 12, 1) << "d/M/yyyy" << "1/12/1974" ; |
1470 | QTest::newRow(dataTag: "2" ) << QDate(1974, 12, 1) << "d/M/yyyyy" << "1/12/1974y" ; |
1471 | QTest::newRow(dataTag: "4" ) << QDate(1974, 1, 1) << "d/M/yyyy" << "1/1/1974" ; |
1472 | QTest::newRow(dataTag: "5" ) << QDate(1974, 1, 1) << "dd/MM/yyy" << "01/01/74y" ; |
1473 | QTest::newRow(dataTag: "6" ) << QDate(1974, 12, 1) << "ddd/MMM/yy" << "Sun/Dec/74" ; |
1474 | QTest::newRow(dataTag: "7" ) << QDate(1974, 12, 1) << "dddd/MMMM/y" << "Sunday/December/y" ; |
1475 | QTest::newRow(dataTag: "8" ) << QDate(1974, 12, 1) << "ddddd/MMMMM/yy" << "Sunday1/December12/74" ; |
1476 | QTest::newRow(dataTag: "9" ) << QDate(1974, 12, 1) << "'dddd'/MMMM/yy" << "dddd/December/74" ; |
1477 | QTest::newRow(dataTag: "10" ) << QDate(1974, 12, 1) << "d'dd'd/MMMM/yyy" << "1dd1/December/74y" ; |
1478 | QTest::newRow(dataTag: "11" ) << QDate(1974, 12, 1) << "d'dd'd/MMM'M'/yy" << "1dd1/DecM/74" ; |
1479 | QTest::newRow(dataTag: "12" ) << QDate(1974, 12, 1) << "d'd'dd/M/yy" << "1d01/12/74" ; |
1480 | |
1481 | QTest::newRow(dataTag: "20" ) << QDate(1974, 12, 1) << "foo" << "foo" ; |
1482 | QTest::newRow(dataTag: "21" ) << QDate(1974, 12, 1) << "'" << "" ; |
1483 | QTest::newRow(dataTag: "22" ) << QDate(1974, 12, 1) << "''" << "'" ; |
1484 | QTest::newRow(dataTag: "23" ) << QDate(1974, 12, 1) << "'''" << "'" ; |
1485 | QTest::newRow(dataTag: "24" ) << QDate(1974, 12, 1) << "\"" << "\"" ; |
1486 | QTest::newRow(dataTag: "25" ) << QDate(1974, 12, 1) << "\"\"" << "\"\"" ; |
1487 | QTest::newRow(dataTag: "26" ) << QDate(1974, 12, 1) << "\"yy\"" << "\"74\"" ; |
1488 | QTest::newRow(dataTag: "27" ) << QDate(1974, 12, 1) << "'\"yy\"'" << "\"yy\"" ; |
1489 | QTest::newRow(dataTag: "28" ) << QDate() << "'\"yy\"'" << "" ; |
1490 | QTest::newRow(dataTag: "29" ) |
1491 | << QDate(1974, 12, 1) << "hh:mm:ss.zzz ap d'd'dd/M/yy" << "hh:mm:ss.zzz ap 1d01/12/74" ; |
1492 | |
1493 | QTest::newRow(dataTag: "dd MMMM yyyy" ) << QDate(1, 1, 1) << "dd MMMM yyyy" << "01 January 0001" ; |
1494 | } |
1495 | |
1496 | void tst_QLocale::formatDate() |
1497 | { |
1498 | QFETCH(QDate, date); |
1499 | QFETCH(QString, format); |
1500 | QFETCH(QString, result); |
1501 | |
1502 | QLocale l(QLocale::C); |
1503 | QCOMPARE(l.toString(date, format), result); |
1504 | QCOMPARE(l.toString(date, QStringView(format)), result); |
1505 | } |
1506 | |
1507 | void tst_QLocale::formatTime_data() |
1508 | { |
1509 | QTest::addColumn<QTime>(name: "time" ); |
1510 | QTest::addColumn<QString>(name: "format" ); |
1511 | QTest::addColumn<QString>(name: "result" ); |
1512 | |
1513 | QTest::newRow(dataTag: "1" ) << QTime(1, 2, 3) << "h:m:s" << "1:2:3" ; |
1514 | QTest::newRow(dataTag: "3" ) << QTime(1, 2, 3) << "H:m:s" << "1:2:3" ; |
1515 | QTest::newRow(dataTag: "4" ) << QTime(1, 2, 3) << "hh:mm:ss" << "01:02:03" ; |
1516 | QTest::newRow(dataTag: "5" ) << QTime(1, 2, 3) << "HH:mm:ss" << "01:02:03" ; |
1517 | QTest::newRow(dataTag: "6" ) << QTime(1, 2, 3) << "hhh:mmm:sss" << "011:022:033" ; |
1518 | |
1519 | QTest::newRow(dataTag: "8" ) << QTime(14, 2, 3) << "h:m:s" << "14:2:3" ; |
1520 | QTest::newRow(dataTag: "9" ) << QTime(14, 2, 3) << "H:m:s" << "14:2:3" ; |
1521 | QTest::newRow(dataTag: "10" ) << QTime(14, 2, 3) << "hh:mm:ss" << "14:02:03" ; |
1522 | QTest::newRow(dataTag: "11" ) << QTime(14, 2, 3) << "HH:mm:ss" << "14:02:03" ; |
1523 | QTest::newRow(dataTag: "12" ) << QTime(14, 2, 3) << "hhh:mmm:sss" << "1414:022:033" ; |
1524 | |
1525 | QTest::newRow(dataTag: "14" ) << QTime(14, 2, 3) << "h:m:s ap" << "2:2:3 pm" ; |
1526 | QTest::newRow(dataTag: "15" ) << QTime(14, 2, 3) << "H:m:s AP" << "14:2:3 PM" ; |
1527 | QTest::newRow(dataTag: "16" ) << QTime(14, 2, 3) << "hh:mm:ss aap" << "02:02:03 pmpm" ; |
1528 | QTest::newRow(dataTag: "17" ) << QTime(14, 2, 3) << "HH:mm:ss AP aa" << "14:02:03 PM pmpm" ; |
1529 | |
1530 | QTest::newRow(dataTag: "18" ) << QTime(1, 2, 3) << "h:m:s ap" << "1:2:3 am" ; |
1531 | QTest::newRow(dataTag: "19" ) << QTime(1, 2, 3) << "H:m:s AP" << "1:2:3 AM" ; |
1532 | |
1533 | QTest::newRow(dataTag: "20" ) << QTime(1, 2, 3) << "foo" << "foo" ; |
1534 | QTest::newRow(dataTag: "21" ) << QTime(1, 2, 3) << "'" << "" ; |
1535 | QTest::newRow(dataTag: "22" ) << QTime(1, 2, 3) << "''" << "'" ; |
1536 | QTest::newRow(dataTag: "23" ) << QTime(1, 2, 3) << "'''" << "'" ; |
1537 | QTest::newRow(dataTag: "24" ) << QTime(1, 2, 3) << "\"" << "\"" ; |
1538 | QTest::newRow(dataTag: "25" ) << QTime(1, 2, 3) << "\"\"" << "\"\"" ; |
1539 | QTest::newRow(dataTag: "26" ) << QTime(1, 2, 3) << "\"H\"" << "\"1\"" ; |
1540 | QTest::newRow(dataTag: "27" ) << QTime(1, 2, 3) << "'\"H\"'" << "\"H\"" ; |
1541 | |
1542 | QTest::newRow(dataTag: "28" ) << QTime(1, 2, 3, 456) << "H:m:s.z" << "1:2:3.456" ; |
1543 | QTest::newRow(dataTag: "29" ) << QTime(1, 2, 3, 456) << "H:m:s.zz" << "1:2:3.456456" ; |
1544 | QTest::newRow(dataTag: "30" ) << QTime(1, 2, 3, 456) << "H:m:s.zzz" << "1:2:3.456" ; |
1545 | QTest::newRow(dataTag: "31" ) << QTime(1, 2, 3, 400) << "H:m:s.z" << "1:2:3.4" ; |
1546 | QTest::newRow(dataTag: "32" ) << QTime(1, 2, 3, 4) << "H:m:s.z" << "1:2:3.004" ; |
1547 | QTest::newRow(dataTag: "33" ) << QTime(1, 2, 3, 4) << "H:m:s.zzz" << "1:2:3.004" ; |
1548 | QTest::newRow(dataTag: "34" ) << QTime() << "H:m:s.zzz" << "" ; |
1549 | QTest::newRow(dataTag: "35" ) << QTime(1, 2, 3, 4) << "dd MM yyyy H:m:s.zzz" << "dd MM yyyy 1:2:3.004" ; |
1550 | } |
1551 | |
1552 | void tst_QLocale::formatTime() |
1553 | { |
1554 | QFETCH(QTime, time); |
1555 | QFETCH(QString, format); |
1556 | QFETCH(QString, result); |
1557 | |
1558 | QLocale l(QLocale::C); |
1559 | QCOMPARE(l.toString(time, format), result); |
1560 | QCOMPARE(l.toString(time, QStringView(format)), result); |
1561 | } |
1562 | |
1563 | |
1564 | void tst_QLocale::formatDateTime_data() |
1565 | { |
1566 | QTest::addColumn<QString>(name: "localeName" ); |
1567 | QTest::addColumn<QDateTime>(name: "dateTime" ); |
1568 | QTest::addColumn<QString>(name: "format" ); |
1569 | QTest::addColumn<QString>(name: "result" ); |
1570 | |
1571 | QTest::newRow(dataTag: "1C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(5, 14, 13)) |
1572 | << "d/M/yyyy hh:h:mm" << "1/12/1974 05:5:14" ; |
1573 | QTest::newRow(dataTag: "2C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1574 | << "d/M/yyyyy h" << "1/12/1974y 15" ; |
1575 | QTest::newRow(dataTag: "4C" ) << "C" << QDateTime(QDate(1974, 1, 1), QTime(15, 14, 13)) |
1576 | << "d/M/yyyy zzz" << "1/1/1974 000" ; |
1577 | QTest::newRow(dataTag: "5C" ) << "C" << QDateTime(QDate(1974, 1, 1), QTime(15, 14, 13)) |
1578 | << "dd/MM/yyy z" << "01/01/74y 0" ; |
1579 | QTest::newRow(dataTag: "6C" ) << "C" << QDateTime(QDate(1974, 12, 2), QTime(15, 14, 13)) |
1580 | << "ddd/MMM/yy AP" << "Mon/Dec/74 PM" ; |
1581 | QTest::newRow(dataTag: "7C" ) << "C" << QDateTime(QDate(1974, 12, 2), QTime(15, 14, 13)) |
1582 | << "dddd/MMMM/y apa" << "Monday/December/y pmpm" ; |
1583 | QTest::newRow(dataTag: "8C" ) << "C" << QDateTime(QDate(1974, 12, 2), QTime(15, 14, 13)) |
1584 | << "ddddd/MMMMM/yy ss" << "Monday2/December12/74 13" ; |
1585 | QTest::newRow(dataTag: "9C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1586 | << "'dddd'/MMMM/yy s" << "dddd/December/74 13" ; |
1587 | QTest::newRow(dataTag: "10C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 4, 13)) |
1588 | << "d'dd'd/MMMM/yyy m'm'mm" << "1dd1/December/74y 4m04" ; |
1589 | QTest::newRow(dataTag: "11C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 3)) |
1590 | << "d'dd'd/MMM'M'/yysss" << "1dd1/DecM/74033" ; |
1591 | QTest::newRow(dataTag: "12C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1592 | << "d'd'dd/M/yyh" << "1d01/12/7415" ; |
1593 | |
1594 | QTest::newRow(dataTag: "dd MMMM yyyy, hh:mm:ss" ) << "C" << QDateTime(QDate(1, 1, 1), QTime(12, 00, 00)) |
1595 | << "dd MMMM yyyy, hh:mm:ss" << "01 January 0001, 12:00:00" ; |
1596 | |
1597 | QTest::newRow(dataTag: "20C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1598 | << "foo" << "foo" ; |
1599 | QTest::newRow(dataTag: "21C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1600 | << "'" << "" ; |
1601 | QTest::newRow(dataTag: "22C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1602 | << "''" << "'" ; |
1603 | QTest::newRow(dataTag: "23C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1604 | << "'''" << "'" ; |
1605 | QTest::newRow(dataTag: "24C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1606 | << "\"" << "\"" ; |
1607 | QTest::newRow(dataTag: "25C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1608 | << "\"\"" << "\"\"" ; |
1609 | QTest::newRow(dataTag: "26C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1610 | << "\"yymm\"" << "\"7414\"" ; |
1611 | QTest::newRow(dataTag: "27C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1612 | << "'\"yymm\"'" << "\"yymm\"" ; |
1613 | QTest::newRow(dataTag: "28C" ) << "C" << QDateTime() |
1614 | << "'\"yymm\"'" << "" ; |
1615 | |
1616 | QTest::newRow(dataTag: "1no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(5, 14, 13)) |
1617 | << "d/M/yyyy hh:h:mm" << "1/12/1974 05:5:14" ; |
1618 | QTest::newRow(dataTag: "2no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1619 | << "d/M/yyyyy h" << "1/12/1974y 15" ; |
1620 | QTest::newRow(dataTag: "4no_NO" ) << "no_NO" << QDateTime(QDate(1974, 1, 1), QTime(15, 14, 13)) |
1621 | << "d/M/yyyy zzz" << "1/1/1974 000" ; |
1622 | QTest::newRow(dataTag: "5no_NO" ) << "no_NO" << QDateTime(QDate(1974, 1, 1), QTime(15, 14, 13)) |
1623 | << "dd/MM/yyy z" << "01/01/74y 0" ; |
1624 | QTest::newRow(dataTag: "6no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 2), QTime(15, 14, 13)) |
1625 | << "ddd/MMM/yy AP" << "man./des./74 P.M." ; |
1626 | QTest::newRow(dataTag: "7no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 2), QTime(15, 14, 13)) |
1627 | << "dddd/MMMM/y apa" << "mandag/desember/y p.m.p.m." ; |
1628 | QTest::newRow(dataTag: "8no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 2), QTime(15, 14, 13)) |
1629 | << "ddddd/MMMMM/yy ss" << "mandag2/desember12/74 13" ; |
1630 | QTest::newRow(dataTag: "9no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1631 | << "'dddd'/MMMM/yy s" << "dddd/desember/74 13" ; |
1632 | QTest::newRow(dataTag: "10no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 4, 13)) |
1633 | << "d'dd'd/MMMM/yyy m'm'mm" << "1dd1/desember/74y 4m04" ; |
1634 | QTest::newRow(dataTag: "11no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 3)) |
1635 | << "d'dd'd/MMM'M'/yysss" << "1dd1/des.M/74033" ; |
1636 | QTest::newRow(dataTag: "12no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1637 | << "d'd'dd/M/yyh" << "1d01/12/7415" ; |
1638 | |
1639 | QTest::newRow(dataTag: "20no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1640 | << "foo" << "foo" ; |
1641 | QTest::newRow(dataTag: "21no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1642 | << "'" << "" ; |
1643 | QTest::newRow(dataTag: "22no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1644 | << "''" << "'" ; |
1645 | QTest::newRow(dataTag: "23no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1646 | << "'''" << "'" ; |
1647 | QTest::newRow(dataTag: "24no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1648 | << "\"" << "\"" ; |
1649 | QTest::newRow(dataTag: "25no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1650 | << "\"\"" << "\"\"" ; |
1651 | QTest::newRow(dataTag: "26no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1652 | << "\"yymm\"" << "\"7414\"" ; |
1653 | QTest::newRow(dataTag: "27no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 14, 13)) |
1654 | << "'\"yymm\"'" << "\"yymm\"" ; |
1655 | QTest::newRow(dataTag: "28no_NO" ) << "no_NO" << QDateTime() |
1656 | << "'\"yymm\"'" << "" ; |
1657 | |
1658 | QDateTime testLongHour(QDate(1999, 12, 31), QTime(23, 59, 59, 999)); |
1659 | QDateTime testShortHour(QDate(1999, 12, 31), QTime(3, 59, 59, 999)); |
1660 | QDateTime testZeroHour(QDate(1999, 12, 31), QTime(0, 59, 59, 999)); |
1661 | |
1662 | QTest::newRow(dataTag: "datetime0" ) << "en_US" << QDateTime() |
1663 | << QString("dd-MM-yyyy hh:mm:ss" ) << QString(); |
1664 | QTest::newRow(dataTag: "datetime1" ) << "en_US" << testLongHour |
1665 | << QString("dd-'mmddyy'MM-yyyy hh:mm:ss.zzz" ) |
1666 | << QString("31-mmddyy12-1999 23:59:59.999" ); |
1667 | QTest::newRow(dataTag: "datetime2" ) << "en_US" << testLongHour |
1668 | << QString("dd-'apAP'MM-yyyy hh:mm:ss.zzz" ) |
1669 | << QString("31-apAP12-1999 23:59:59.999" ); |
1670 | QTest::newRow(dataTag: "datetime3" ) << "en_US" << testLongHour |
1671 | << QString("Apdd-MM-yyyy hh:mm:ss.zzz" ) |
1672 | << QString("PMp31-12-1999 11:59:59.999" ); |
1673 | QTest::newRow(dataTag: "datetime4" ) << "en_US" << testLongHour |
1674 | << QString("'ap'apdd-MM-yyyy 'AP'hh:mm:ss.zzz" ) |
1675 | << QString("appm31-12-1999 AP11:59:59.999" ); |
1676 | QTest::newRow(dataTag: "datetime5" ) << "en_US" << testLongHour |
1677 | << QString("'''" ) << QString("'" ); |
1678 | QTest::newRow(dataTag: "datetime6" ) << "en_US" << testLongHour |
1679 | << QString("'ap" ) << QString("ap" ); |
1680 | QTest::newRow(dataTag: "datetime7" ) << "en_US" << testLongHour |
1681 | << QString("' ' 'hh' hh" ) << QString(" hh 23" ); |
1682 | QTest::newRow(dataTag: "datetime8" ) << "en_US" << testLongHour |
1683 | << QString("d'foobar'" ) << QString("31foobar" ); |
1684 | QTest::newRow(dataTag: "datetime9" ) << "en_US" << testShortHour |
1685 | << QString("hhhhh" ) << QString("03033" ); |
1686 | QTest::newRow(dataTag: "datetime11" ) << "en_US" << testLongHour |
1687 | << QString("HHHhhhAaAPap" ) << QString("23231111PMpmPMpm" ); |
1688 | QTest::newRow(dataTag: "datetime12" ) << "en_US" << testShortHour |
1689 | << QString("HHHhhhAaAPap" ) << QString("033033AMamAMam" ); |
1690 | QTest::newRow(dataTag: "datetime13" ) << "en_US" << QDateTime(QDate(1974, 12, 1), QTime(14, 14, 20)) |
1691 | << QString("hh''mm''ss dd''MM''yyyy" ) |
1692 | << QString("14'14'20 01'12'1974" ); |
1693 | QTest::newRow(dataTag: "AM no p" ) << "en_US" << testZeroHour |
1694 | << QString("hhAX" ) << QString("12AMX" ); |
1695 | QTest::newRow(dataTag: "AM no p, x 2" ) << "en_US" << testShortHour |
1696 | << QString("hhhhhaA" ) << QString("03033amAM" ); |
1697 | QTest::newRow(dataTag: "am 0 hour" ) << "en_US" << testZeroHour |
1698 | << QString("hAP" ) << QString("12AM" ); |
1699 | QTest::newRow(dataTag: "AM zero hour" ) << "en_US" << testZeroHour |
1700 | << QString("hhAP" ) << QString("12AM" ); |
1701 | QTest::newRow(dataTag: "dddd" ) << "en_US" << testZeroHour |
1702 | << QString("dddd" ) << QString("Friday" ); |
1703 | QTest::newRow(dataTag: "ddd" ) << "en_US" << testZeroHour |
1704 | << QString("ddd" ) << QString("Fri" ); |
1705 | QTest::newRow(dataTag: "MMMM" ) << "en_US" << testZeroHour |
1706 | << QString("MMMM" ) << QString("December" ); |
1707 | QTest::newRow(dataTag: "MMM" ) << "en_US" << testZeroHour |
1708 | << QString("MMM" ) << QString("Dec" ); |
1709 | QTest::newRow(dataTag: "empty" ) << "en_US" << testZeroHour |
1710 | << QString("" ) << QString("" ); |
1711 | } |
1712 | |
1713 | void tst_QLocale::formatDateTime() |
1714 | { |
1715 | QFETCH(QString, localeName); |
1716 | QFETCH(QDateTime, dateTime); |
1717 | QFETCH(QString, format); |
1718 | QFETCH(QString, result); |
1719 | |
1720 | QLocale l(localeName); |
1721 | QCOMPARE(l.toString(dateTime, format), result); |
1722 | QCOMPARE(l.toString(dateTime, QStringView(format)), result); |
1723 | } |
1724 | |
1725 | void tst_QLocale::formatTimeZone() |
1726 | { |
1727 | QLocale enUS("en_US" ); |
1728 | |
1729 | QDateTime dt1(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, 60 * 60); |
1730 | QCOMPARE(enUS.toString(dt1, "t" ), QLatin1String("UTC+01:00" )); |
1731 | |
1732 | QDateTime dt2(QDate(2013, 1, 1), QTime(1, 0, 0), Qt::OffsetFromUTC, -60 * 60); |
1733 | QCOMPARE(enUS.toString(dt2, "t" ), QLatin1String("UTC-01:00" )); |
1734 | |
1735 | QDateTime dt3(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::UTC); |
1736 | QCOMPARE(enUS.toString(dt3, "t" ), QLatin1String("UTC" )); |
1737 | |
1738 | // LocalTime should vary |
1739 | if (europeanTimeZone) { |
1740 | // Time definitely in Standard Time |
1741 | QDateTime dt4(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime); |
1742 | #ifdef Q_OS_WIN |
1743 | QEXPECT_FAIL("" , "Windows only returns long name (QTBUG-32759)" , Continue); |
1744 | #endif // Q_OS_WIN |
1745 | QCOMPARE(enUS.toString(dt4, "t" ), QLatin1String("CET" )); |
1746 | |
1747 | // Time definitely in Daylight Time |
1748 | QDateTime dt5(QDate(2013, 6, 1), QTime(0, 0, 0), Qt::LocalTime); |
1749 | #ifdef Q_OS_WIN |
1750 | QEXPECT_FAIL("" , "Windows only returns long name (QTBUG-32759)" , Continue); |
1751 | #endif // Q_OS_WIN |
1752 | QCOMPARE(enUS.toString(dt5, "t" ), QLatin1String("CEST" )); |
1753 | } else { |
1754 | qDebug(msg: "(Skipped some CET-only tests)" ); |
1755 | } |
1756 | |
1757 | #if QT_CONFIG(timezone) |
1758 | const QTimeZone berlin("Europe/Berlin" ); |
1759 | const QDateTime jan(QDate(2010, 1, 1).startOfDay(zone: berlin)); |
1760 | const QDateTime jul(QDate(2010, 7, 1).startOfDay(zone: berlin)); |
1761 | |
1762 | QCOMPARE(enUS.toString(jan, "t" ), berlin.abbreviation(jan)); |
1763 | QCOMPARE(enUS.toString(jul, "t" ), berlin.abbreviation(jul)); |
1764 | #endif |
1765 | |
1766 | // Current datetime should return current abbreviation |
1767 | QCOMPARE(enUS.toString(QDateTime::currentDateTime(), "t" ), |
1768 | QDateTime::currentDateTime().timeZoneAbbreviation()); |
1769 | |
1770 | // Time on its own will always be current local time zone |
1771 | QCOMPARE(enUS.toString(QTime(1, 2, 3), "t" ), |
1772 | QDateTime::currentDateTime().timeZoneAbbreviation()); |
1773 | } |
1774 | |
1775 | void tst_QLocale::toDateTime_data() |
1776 | { |
1777 | QTest::addColumn<QString>(name: "localeName" ); |
1778 | QTest::addColumn<QDateTime>(name: "result" ); |
1779 | QTest::addColumn<QString>(name: "format" ); |
1780 | QTest::addColumn<QString>(name: "string" ); |
1781 | QTest::addColumn<bool>(name: "clean" ); // No non-format letters in format string |
1782 | |
1783 | QTest::newRow(dataTag: "1C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(5, 14, 0)) |
1784 | << "d/M/yyyy hh:h:mm" << "1/12/1974 05:5:14" << true; |
1785 | QTest::newRow(dataTag: "2C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 0, 0)) |
1786 | << "d/M/yyyyy h" << "1/12/1974y 15" << false; |
1787 | QTest::newRow(dataTag: "4C" ) << "C" << QDateTime(QDate(1974, 1, 1), QTime(0, 0, 0, 1)) |
1788 | << "d/M/yyyy zzz" << "1/1/1974 001" << true; |
1789 | QTest::newRow(dataTag: "5C" ) << "C" << QDateTime(QDate(1974, 1, 1), QTime(0, 0, 0, 1)) |
1790 | << "dd/MM/yyy z" << "01/01/74y 001" << false; |
1791 | QTest::newRow(dataTag: "6C" ) << "C" << QDateTime(QDate(1974, 1, 1), QTime(0, 0, 0, 100)) |
1792 | << "dd/MM/yyy z" << "01/01/74y 1" << false; |
1793 | QTest::newRow(dataTag: "8C" ) << "C" << QDateTime(QDate(1974, 12, 2), QTime(0, 0, 13)) |
1794 | << "ddddd/MMMMM/yy ss" << "Monday2/December12/74 13" << true; |
1795 | QTest::newRow(dataTag: "9C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(0, 0, 13)) |
1796 | << "'dddd'/MMMM/yy s" << "dddd/December/74 13" << false; |
1797 | QTest::newRow(dataTag: "10C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(0, 4, 0)) |
1798 | << "d'dd'd/MMMM/yyy m'm'mm" << "1dd1/December/74y 4m04" << false; |
1799 | QTest::newRow(dataTag: "11C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(0, 0, 3)) |
1800 | << "d'dd'd/MMM'M'/yysss" << "1dd1/DecM/74033" << false; |
1801 | QTest::newRow(dataTag: "12C" ) << "C" << QDateTime(QDate(1974, 12, 1), QTime(15, 0, 0)) |
1802 | << "d'd'dd/M/yyh" << "1d01/12/7415" << false; |
1803 | // Unpadded value for fixed-width field is wrong: |
1804 | QTest::newRow(dataTag: "bad-day-C" ) << "C" << QDateTime() << "dd-MMM-yy" << "4-Jun-11" << true; |
1805 | QTest::newRow(dataTag: "bad-month-C" ) << "C" << QDateTime() << "d-MM-yy" << "4-6-11" << true; |
1806 | QTest::newRow(dataTag: "bad-year-C" ) << "C" << QDateTime() << "d-MMM-yyyy" << "4-Jun-11" << true; |
1807 | QTest::newRow(dataTag: "bad-hour-C" ) << "C" << QDateTime() << "d-MMM-yy hh:m" << "4-Jun-11 1:2" << true; |
1808 | QTest::newRow(dataTag: "bad-min-C" ) << "C" << QDateTime() << "d-MMM-yy h:mm" << "4-Jun-11 1:2" << true; |
1809 | QTest::newRow(dataTag: "bad-sec-C" ) |
1810 | << "C" << QDateTime() << "d-MMM-yy h:m:ss" << "4-Jun-11 1:2:3" << true; |
1811 | QTest::newRow(dataTag: "bad-milli-C" ) |
1812 | << "C" << QDateTime() << "d-MMM-yy h:m:s.zzz" << "4-Jun-11 1:2:3.4" << true; |
1813 | QTest::newRow(dataTag: "ok-C" ) << "C" << QDateTime(QDate(1911, 6, 4), QTime(1, 2, 3, 400)) |
1814 | << "d-MMM-yy h:m:s.z" << "4-Jun-11 1:2:3.4" << true; |
1815 | |
1816 | QTest::newRow(dataTag: "1no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(5, 14, 0)) |
1817 | << "d/M/yyyy hh:h:mm" << "1/12/1974 05:5:14" << true; |
1818 | QTest::newRow(dataTag: "2no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 0, 0)) |
1819 | << "d/M/yyyyy h" << "1/12/1974y 15" << false; |
1820 | QTest::newRow(dataTag: "4no_NO" ) << "no_NO" << QDateTime(QDate(1974, 1, 1), QTime(0, 0, 0)) |
1821 | << "d/M/yyyy zzz" << "1/1/1974 000" << true; |
1822 | QTest::newRow(dataTag: "5no_NO" ) << "no_NO" << QDateTime(QDate(1974, 1, 1), QTime(0, 0, 0)) |
1823 | << "dd/MM/yyy z" << "01/01/74y 0" << false; |
1824 | QTest::newRow(dataTag: "8no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 2), QTime(0, 0, 13)) |
1825 | << "ddddd/MMMMM/yy ss" << "mandag2/desember12/74 13" << true; |
1826 | QTest::newRow(dataTag: "9no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(0, 0, 13)) |
1827 | << "'dddd'/MMMM/yy s" << "dddd/desember/74 13" << false; |
1828 | QTest::newRow(dataTag: "10no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(0, 4, 0)) |
1829 | << "d'dd'd/MMMM/yyy m'm'mm" << "1dd1/desember/74y 4m04" << false; |
1830 | QTest::newRow(dataTag: "11no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(0, 0, 3)) |
1831 | << "d'dd'd/MMM'M'/yysss" << "1dd1/des.M/74033" << false; |
1832 | QTest::newRow(dataTag: "12no_NO" ) << "no_NO" << QDateTime(QDate(1974, 12, 1), QTime(15, 0, 0)) |
1833 | << "d'd'dd/M/yyh" << "1d01/12/7415" << false; |
1834 | |
1835 | QTest::newRow(dataTag: "RFC-1123" ) |
1836 | << "C" << QDateTime(QDate(2007, 11, 1), QTime(18, 8, 30)) |
1837 | << "ddd, dd MMM yyyy hh:mm:ss 'GMT'" << "Thu, 01 Nov 2007 18:08:30 GMT" << false; |
1838 | |
1839 | QTest::newRow(dataTag: "longFormat" ) |
1840 | << "en_US" << QDateTime(QDate(2009, 1, 5), QTime(11, 48, 32)) |
1841 | << "dddd, MMMM d, yyyy h:mm:ss AP " << "Monday, January 5, 2009 11:48:32 AM " << true; |
1842 | |
1843 | const QDateTime dt(QDate(2017, 02, 25), QTime(17, 21, 25)); |
1844 | // These formats correspond to the locale formats, with the timezone removed. |
1845 | // We hardcode them in case an update to the locale DB changes them. |
1846 | |
1847 | QTest::newRow(dataTag: "C:long" ) << "C" << dt << "dddd, d MMMM yyyy HH:mm:ss" |
1848 | << "Saturday, 25 February 2017 17:21:25" << true; |
1849 | QTest::newRow(dataTag: "C:short" ) |
1850 | << "C" << dt << "d MMM yyyy HH:mm:ss" << "25 Feb 2017 17:21:25" << true; |
1851 | QTest::newRow(dataTag: "C:narrow" ) |
1852 | << "C" << dt << "d MMM yyyy HH:mm:ss" << "25 Feb 2017 17:21:25" << true; |
1853 | |
1854 | QTest::newRow(dataTag: "fr:long" ) << "fr" << dt << "dddd d MMMM yyyy HH:mm:ss" |
1855 | << "Samedi 25 février 2017 17:21:25" << true; |
1856 | QTest::newRow(dataTag: "fr:short" ) |
1857 | << "fr" << dt.addSecs(secs: -25) << "dd/MM/yyyy HH:mm" << "25/02/2017 17:21" << true; |
1858 | |
1859 | // In Turkish, the word for Friday ("Cuma") is a prefix for the word for |
1860 | // Saturday ("Cumartesi") |
1861 | QTest::newRow(dataTag: "tr:long" ) |
1862 | << "tr" << dt << "d MMMM yyyy dddd HH:mm:ss" << "25 Şubat 2017 Cumartesi 17:21:25" << true; |
1863 | QTest::newRow(dataTag: "tr:long2" ) << "tr" << dt.addDays(days: -1) << "d MMMM yyyy dddd HH:mm:ss" |
1864 | << "24 Şubat 2017 Cuma 17:21:25" << true; |
1865 | QTest::newRow(dataTag: "tr:mashed" ) |
1866 | << "tr" << dt << "d MMMMyyyy ddddHH:mm:ss" << "25 Şubat2017 Cumartesi17:21:25" << true; |
1867 | QTest::newRow(dataTag: "tr:mashed2" ) << "tr" << dt.addDays(days: -1) << "d MMMMyyyy ddddHH:mm:ss" |
1868 | << "24 Şubat2017 Cuma17:21:25" << true; |
1869 | QTest::newRow(dataTag: "tr:short" ) |
1870 | << "tr" << dt.addSecs(secs: -25) << "d.MM.yyyy HH:mm" << "25.02.2017 17:21" << true; |
1871 | } |
1872 | |
1873 | void tst_QLocale::toDateTime() |
1874 | { |
1875 | QFETCH(QString, localeName); |
1876 | QFETCH(QDateTime, result); |
1877 | QFETCH(QString, format); |
1878 | QFETCH(QString, string); |
1879 | QFETCH(bool, clean); |
1880 | |
1881 | QLocale l(localeName); |
1882 | QCOMPARE(l.toDateTime(string, format), result); |
1883 | if (clean) { |
1884 | QCOMPARE(l.toDateTime(string.toLower(), format), result); |
1885 | QCOMPARE(l.toDateTime(string.toUpper(), format), result); |
1886 | } |
1887 | |
1888 | if (l.dateTimeFormat(format: QLocale::LongFormat) == format) |
1889 | QCOMPARE(l.toDateTime(string, QLocale::LongFormat), result); |
1890 | if (l.dateTimeFormat(format: QLocale::ShortFormat) == format) |
1891 | QCOMPARE(l.toDateTime(string, QLocale::ShortFormat), result); |
1892 | } |
1893 | |
1894 | #ifdef Q_OS_MAC |
1895 | |
1896 | // Format number string according to system locale settings. |
1897 | // Expected in format is US "1,234.56". |
1898 | QString systemLocaleFormatNumber(QString &&numberString) |
1899 | { |
1900 | QLocale locale = QLocale::system(); |
1901 | QString numberStringMunged = |
1902 | numberString.replace(QChar(','), QChar('G')).replace(QChar('.'), QChar('D')); |
1903 | if (locale.numberOptions() & QLocale::OmitGroupSeparator) |
1904 | numberStringMunged.remove(QLatin1Char('G')); |
1905 | else |
1906 | numberStringMunged.replace(QChar('G'), locale.groupSeparator()); |
1907 | return numberStringMunged.replace(QChar('D'), locale.decimalPoint()); |
1908 | } |
1909 | |
1910 | void tst_QLocale::macDefaultLocale() |
1911 | { |
1912 | QLocale locale = QLocale::system(); |
1913 | |
1914 | if (locale.name() != QLatin1String("en_US" )) |
1915 | QSKIP("This test only tests for en_US" ); |
1916 | |
1917 | QTime invalidTime; |
1918 | QDate invalidDate; |
1919 | QCOMPARE(locale.toString(invalidTime, QLocale::ShortFormat), QString()); |
1920 | QCOMPARE(locale.toString(invalidDate, QLocale::ShortFormat), QString()); |
1921 | QCOMPARE(locale.toString(invalidTime, QLocale::NarrowFormat), QString()); |
1922 | QCOMPARE(locale.toString(invalidDate, QLocale::NarrowFormat), QString()); |
1923 | QCOMPARE(locale.toString(invalidTime, QLocale::LongFormat), QString()); |
1924 | QCOMPARE(locale.toString(invalidDate, QLocale::LongFormat), QString()); |
1925 | |
1926 | // On OS X the decimal point and group separator are configurable |
1927 | // independently of the locale. Verify that they have one of the |
1928 | // allowed values and are not the same. |
1929 | QVERIFY(locale.decimalPoint() == QChar('.') || locale.decimalPoint() == QChar(',')); |
1930 | if (!(locale.numberOptions() & QLocale::OmitGroupSeparator)) { |
1931 | QVERIFY(locale.groupSeparator() == QChar(',') |
1932 | || locale.groupSeparator() == QChar('.') |
1933 | || locale.groupSeparator() == QChar('\xA0') // no-breaking space |
1934 | || locale.groupSeparator() == QChar('\'') |
1935 | || locale.groupSeparator() == QChar()); |
1936 | QVERIFY(locale.decimalPoint() != locale.groupSeparator()); |
1937 | } |
1938 | |
1939 | // make sure we are using the system to parse them |
1940 | QCOMPARE(locale.toString(1234.56), systemLocaleFormatNumber(QString("1,234.56" ))); |
1941 | |
1942 | QTime testTime = QTime(1, 2, 3); |
1943 | QTime utcTime = QDateTime(QDate::currentDate(), testTime).toUTC().time(); |
1944 | int diff = testTime.hour() - utcTime.hour(); |
1945 | |
1946 | // Check if local time and utc time are on opposite sides of the 24-hour wrap-around. |
1947 | if (diff < -12) |
1948 | diff += 24; |
1949 | if (diff > 12) |
1950 | diff -= 24; |
1951 | |
1952 | const QString timeString = locale.toString(testTime, QLocale::LongFormat); |
1953 | QVERIFY(timeString.contains(QString("1:02:03" ))); |
1954 | |
1955 | // To run this test make sure "Curreny" is US Dollar in System Preferences->Language & Region->Advanced. |
1956 | if (locale.currencySymbol() == QString("$" )) { |
1957 | QCOMPARE(locale.toCurrencyString(qulonglong(1234)), |
1958 | systemLocaleFormatNumber(QString("$1,234.00" ))); |
1959 | QCOMPARE(locale.toCurrencyString(double(1234.56)), |
1960 | systemLocaleFormatNumber(QString("$1,234.56" ))); |
1961 | } |
1962 | |
1963 | // Depending on the configured time zone, the time string might not |
1964 | // contain a GMT specifier. (Sometimes it just names the zone, like "CEST") |
1965 | QLatin1String gmt("GMT" ); |
1966 | if (timeString.contains(gmt) && diff) { |
1967 | QLatin1Char sign(diff < 0 ? '-' : '+'); |
1968 | QString number(QString::number(qAbs(diff))); |
1969 | const QString expect = gmt + sign + number; |
1970 | |
1971 | if (diff < 10) { |
1972 | const QString zeroed = gmt + sign + QLatin1Char('0') + number; |
1973 | |
1974 | QVERIFY2(timeString.contains(expect) || timeString.contains(zeroed), |
1975 | qPrintable(QString("timeString `%1', expected GMT specifier `%2' or `%3'" ) |
1976 | .arg(timeString).arg(expect).arg(zeroed))); |
1977 | } else { |
1978 | QVERIFY2(timeString.contains(expect), |
1979 | qPrintable(QString("timeString `%1', expected GMT specifier `%2'" ) |
1980 | .arg(timeString).arg(expect))); |
1981 | } |
1982 | } |
1983 | QCOMPARE(locale.dayName(1), QString("Monday" )); |
1984 | QCOMPARE(locale.dayName(7), QString("Sunday" )); |
1985 | QCOMPARE(locale.monthName(1), QString("January" )); |
1986 | QCOMPARE(locale.monthName(12), QString("December" )); |
1987 | QCOMPARE(locale.quoteString("string" ), |
1988 | QString::fromUtf8("\xe2\x80\x9c" "string" "\xe2\x80\x9d" )); |
1989 | QCOMPARE(locale.quoteString("string" , QLocale::AlternateQuotation), |
1990 | QString::fromUtf8("\xe2\x80\x98" "string" "\xe2\x80\x99" )); |
1991 | |
1992 | QList<Qt::DayOfWeek> days; |
1993 | days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday; |
1994 | QCOMPARE(locale.weekdays(), days); |
1995 | |
1996 | } |
1997 | #endif // Q_OS_MAC |
1998 | |
1999 | #if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) |
2000 | #include <qt_windows.h> |
2001 | |
2002 | static QString getWinLocaleInfo(LCTYPE type) |
2003 | { |
2004 | LCID id = GetThreadLocale(); |
2005 | int cnt = GetLocaleInfo(id, type, 0, 0) * 2; |
2006 | |
2007 | if (cnt == 0) { |
2008 | qWarning().nospace() << "QLocale: empty windows locale info (" << type << ')'; |
2009 | return QString(); |
2010 | } |
2011 | cnt /= sizeof(wchar_t); |
2012 | QScopedArrayPointer<wchar_t> buf(new wchar_t[cnt]); |
2013 | cnt = GetLocaleInfo(id, type, buf.data(), cnt); |
2014 | |
2015 | if (cnt == 0) { |
2016 | qWarning().nospace() << "QLocale: empty windows locale info (" << type << ')'; |
2017 | return QString(); |
2018 | } |
2019 | return QString::fromWCharArray(buf.data()); |
2020 | } |
2021 | |
2022 | static void setWinLocaleInfo(LCTYPE type, const QString &value) |
2023 | { |
2024 | LCID id = GetThreadLocale(); |
2025 | SetLocaleInfo(id, type, reinterpret_cast<const wchar_t*>(value.utf16())); |
2026 | } |
2027 | |
2028 | #ifndef LOCALE_SSHORTTIME |
2029 | # define LOCALE_SSHORTTIME 0x00000079 |
2030 | #endif |
2031 | |
2032 | class RestoreLocaleHelper |
2033 | { |
2034 | public: |
2035 | RestoreLocaleHelper() |
2036 | { |
2037 | m_decimal = getWinLocaleInfo(LOCALE_SDECIMAL); |
2038 | m_thousand = getWinLocaleInfo(LOCALE_STHOUSAND); |
2039 | m_sdate = getWinLocaleInfo(LOCALE_SSHORTDATE); |
2040 | m_ldate = getWinLocaleInfo(LOCALE_SLONGDATE); |
2041 | m_time = getWinLocaleInfo(LOCALE_SSHORTTIME); |
2042 | } |
2043 | |
2044 | ~RestoreLocaleHelper() |
2045 | { |
2046 | // restore these, or the user will get a surprise |
2047 | setWinLocaleInfo(LOCALE_SDECIMAL, m_decimal); |
2048 | setWinLocaleInfo(LOCALE_STHOUSAND, m_thousand); |
2049 | setWinLocaleInfo(LOCALE_SSHORTDATE, m_sdate); |
2050 | setWinLocaleInfo(LOCALE_SLONGDATE, m_ldate); |
2051 | setWinLocaleInfo(LOCALE_SSHORTTIME, m_time); |
2052 | |
2053 | QSystemLocale dummy; // to provoke a refresh of the system locale |
2054 | } |
2055 | |
2056 | QString m_decimal, m_thousand, m_sdate, m_ldate, m_time; |
2057 | }; |
2058 | |
2059 | void tst_QLocale::windowsDefaultLocale() |
2060 | { |
2061 | RestoreLocaleHelper systemLocale; |
2062 | // set weird system defaults and make sure we're using them |
2063 | setWinLocaleInfo(LOCALE_SDECIMAL, QLatin1String("@" )); |
2064 | setWinLocaleInfo(LOCALE_STHOUSAND, QLatin1String("?" )); |
2065 | const QString shortDateFormat = QStringLiteral("d*M*yyyy" ); |
2066 | setWinLocaleInfo(LOCALE_SSHORTDATE, shortDateFormat); |
2067 | const QString longDateFormat = QStringLiteral("d@M@yyyy" ); |
2068 | setWinLocaleInfo(LOCALE_SLONGDATE, longDateFormat); |
2069 | const QString shortTimeFormat = QStringLiteral("h^m^s" ); |
2070 | setWinLocaleInfo(LOCALE_SSHORTTIME, shortTimeFormat); |
2071 | const QString longTimeFormat = QStringLiteral("HH%mm%ss" ); |
2072 | setWinLocaleInfo(LOCALE_STIMEFORMAT, longTimeFormat); |
2073 | |
2074 | QSystemLocale dummy; // to provoke a refresh of the system locale |
2075 | QLocale locale = QLocale::system(); |
2076 | |
2077 | // make sure we are seeing the system's format strings |
2078 | QCOMPARE(locale.decimalPoint(), QChar('@')); |
2079 | QCOMPARE(locale.groupSeparator(), QChar('?')); |
2080 | QCOMPARE(locale.dateFormat(QLocale::ShortFormat), shortDateFormat); |
2081 | QCOMPARE(locale.dateFormat(QLocale::LongFormat), longDateFormat); |
2082 | QCOMPARE(locale.timeFormat(QLocale::ShortFormat), shortTimeFormat); |
2083 | QCOMPARE(locale.dateTimeFormat(QLocale::ShortFormat), |
2084 | shortDateFormat + QLatin1Char(' ') + shortTimeFormat); |
2085 | const QString expectedLongDateTimeFormat |
2086 | = longDateFormat + QLatin1Char(' ') + longTimeFormat; |
2087 | QCOMPARE(locale.dateTimeFormat(QLocale::LongFormat), expectedLongDateTimeFormat); |
2088 | |
2089 | // make sure we are using the system to parse them |
2090 | QCOMPARE(locale.toString(1234.56), QString("1?234@56" )); |
2091 | QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat), QString("1*12*1974" )); |
2092 | QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::NarrowFormat), |
2093 | locale.toString(QDate(1974, 12, 1), QLocale::ShortFormat)); |
2094 | QCOMPARE(locale.toString(QDate(1974, 12, 1), QLocale::LongFormat), QString("1@12@1974" )); |
2095 | const QString expectedFormattedShortTimeSeconds = QStringLiteral("1^2^3" ); |
2096 | const QString expectedFormattedShortTime = QStringLiteral("1^2" ); |
2097 | QCOMPARE(locale.toString(QTime(1,2,3), QLocale::ShortFormat), expectedFormattedShortTime); |
2098 | QCOMPARE(locale.toString(QTime(1,2,3), QLocale::NarrowFormat), |
2099 | locale.toString(QTime(1,2,3), QLocale::ShortFormat)); |
2100 | const QString expectedFormattedLongTime = QStringLiteral("01%02%03" ); |
2101 | QCOMPARE(locale.toString(QTime(1,2,3), QLocale::LongFormat), expectedFormattedLongTime); |
2102 | QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::ShortFormat), |
2103 | QStringLiteral("1*12*1974 " ) + expectedFormattedShortTime); |
2104 | QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::NarrowFormat), |
2105 | locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::ShortFormat)); |
2106 | QCOMPARE(locale.toString(QDateTime(QDate(1974, 12, 1), QTime(1,2,3)), QLocale::LongFormat), |
2107 | QStringLiteral("1@12@1974 " ) + expectedFormattedLongTime); |
2108 | } |
2109 | #endif // Q_OS_WIN but !Q_OS_WINRT |
2110 | |
2111 | void tst_QLocale::numberOptions() |
2112 | { |
2113 | bool ok; |
2114 | |
2115 | QLocale locale(QLocale::C); |
2116 | QCOMPARE(locale.numberOptions(), QLocale::OmitGroupSeparator); |
2117 | QCOMPARE(locale.toInt(QString("12345" ), &ok), 12345); |
2118 | QVERIFY(ok); |
2119 | QCOMPARE(locale.toInt(QString("12345" ), &ok), 12345); |
2120 | QVERIFY(ok); |
2121 | QCOMPARE(locale.toString(12345), QString("12345" )); |
2122 | |
2123 | locale.setNumberOptions({ }); |
2124 | QCOMPARE(locale.numberOptions(), 0); |
2125 | QCOMPARE(locale.toInt(QString("12,345" ), &ok), 12345); |
2126 | QVERIFY(ok); |
2127 | QCOMPARE(locale.toInt(QString("12345" ), &ok), 12345); |
2128 | QVERIFY(ok); |
2129 | QCOMPARE(locale.toString(12345), QString("12,345" )); |
2130 | |
2131 | locale.setNumberOptions(QLocale::RejectGroupSeparator); |
2132 | QCOMPARE(locale.numberOptions(), QLocale::RejectGroupSeparator); |
2133 | locale.toInt(s: QString("12,345" ), ok: &ok); |
2134 | QVERIFY(!ok); |
2135 | QCOMPARE(locale.toInt(QString("12345" ), &ok), 12345); |
2136 | QVERIFY(ok); |
2137 | QCOMPARE(locale.toString(12345), QString("12,345" )); |
2138 | |
2139 | QLocale locale2 = locale; |
2140 | QCOMPARE(locale2.numberOptions(), QLocale::RejectGroupSeparator); |
2141 | |
2142 | QCOMPARE(locale.toString(12.4, 'e', 2), QString("1.24e+01" )); |
2143 | locale.setNumberOptions(QLocale::OmitLeadingZeroInExponent); |
2144 | QCOMPARE(locale.numberOptions(), QLocale::OmitLeadingZeroInExponent); |
2145 | QCOMPARE(locale.toString(12.4, 'e', 2), QString("1.24e+1" )); |
2146 | |
2147 | locale.toDouble(s: QString("1.24e+01" ), ok: &ok); |
2148 | QVERIFY(ok); |
2149 | locale.setNumberOptions(QLocale::RejectLeadingZeroInExponent); |
2150 | QCOMPARE(locale.numberOptions(), QLocale::RejectLeadingZeroInExponent); |
2151 | locale.toDouble(s: QString("1.24e+1" ), ok: &ok); |
2152 | QVERIFY(ok); |
2153 | locale.toDouble(s: QString("1.24e+01" ), ok: &ok); |
2154 | QVERIFY(!ok); |
2155 | |
2156 | QCOMPARE(locale.toString(12.4, 'g', 5), QString("12.4" )); |
2157 | locale.setNumberOptions(QLocale::IncludeTrailingZeroesAfterDot); |
2158 | QCOMPARE(locale.numberOptions(), QLocale::IncludeTrailingZeroesAfterDot); |
2159 | QCOMPARE(locale.toString(12.4, 'g', 5), QString("12.400" )); |
2160 | |
2161 | locale.toDouble(s: QString("1.24e+01" ), ok: &ok); |
2162 | QVERIFY(ok); |
2163 | locale.toDouble(s: QString("1.2400e+01" ), ok: &ok); |
2164 | QVERIFY(ok); |
2165 | locale.toDouble(s: QString("12.4" ), ok: &ok); |
2166 | QVERIFY(ok); |
2167 | locale.toDouble(s: QString("12.400" ), ok: &ok); |
2168 | QVERIFY(ok); |
2169 | locale.setNumberOptions(QLocale::RejectTrailingZeroesAfterDot); |
2170 | QCOMPARE(locale.numberOptions(), QLocale::RejectTrailingZeroesAfterDot); |
2171 | locale.toDouble(s: QString("1.24e+01" ), ok: &ok); |
2172 | QVERIFY(ok); |
2173 | locale.toDouble(s: QString("1.2400e+01" ), ok: &ok); |
2174 | QVERIFY(!ok); |
2175 | locale.toDouble(s: QString("12.4" ), ok: &ok); |
2176 | QVERIFY(ok); |
2177 | locale.toDouble(s: QString("12.400" ), ok: &ok); |
2178 | QVERIFY(!ok); |
2179 | } |
2180 | |
2181 | void tst_QLocale::negativeNumbers() |
2182 | { |
2183 | QLocale locale(QLocale::C); |
2184 | |
2185 | bool ok; |
2186 | int i; |
2187 | |
2188 | i = locale.toInt(s: QLatin1String("-100" ), ok: &ok); |
2189 | QVERIFY(ok); |
2190 | QCOMPARE(i, -100); |
2191 | |
2192 | i = locale.toInt(s: QLatin1String("-1,000" ), ok: &ok); |
2193 | QVERIFY(ok); |
2194 | QCOMPARE(i, -1000); |
2195 | |
2196 | i = locale.toInt(s: QLatin1String("-1000" ), ok: &ok); |
2197 | QVERIFY(ok); |
2198 | QCOMPARE(i, -1000); |
2199 | |
2200 | i = locale.toInt(s: QLatin1String("-10,000" ), ok: &ok); |
2201 | QVERIFY(ok); |
2202 | QCOMPARE(i, -10000); |
2203 | |
2204 | i = locale.toInt(s: QLatin1String("-10000" ), ok: &ok); |
2205 | QVERIFY(ok); |
2206 | QCOMPARE(i, -10000); |
2207 | |
2208 | i = locale.toInt(s: QLatin1String("-100,000" ), ok: &ok); |
2209 | QVERIFY(ok); |
2210 | QCOMPARE(i, -100000); |
2211 | |
2212 | i = locale.toInt(s: QLatin1String("-100000" ), ok: &ok); |
2213 | QVERIFY(ok); |
2214 | QCOMPARE(i, -100000); |
2215 | |
2216 | i = locale.toInt(s: QLatin1String("-1,000,000" ), ok: &ok); |
2217 | QVERIFY(ok); |
2218 | QCOMPARE(i, -1000000); |
2219 | |
2220 | i = locale.toInt(s: QLatin1String("-1000000" ), ok: &ok); |
2221 | QVERIFY(ok); |
2222 | QCOMPARE(i, -1000000); |
2223 | } |
2224 | |
2225 | #include <private/qlocale_p.h> |
2226 | #include <private/qlocale_data_p.h> |
2227 | |
2228 | static const int locale_data_count = sizeof(locale_data)/sizeof(locale_data[0]); |
2229 | |
2230 | void tst_QLocale::testNames_data() |
2231 | { |
2232 | QTest::addColumn<int>(name: "language" ); |
2233 | QTest::addColumn<int>(name: "country" ); |
2234 | |
2235 | QLocale::setDefault(QLocale(QLocale::C)); // Ensures predictable fall-backs |
2236 | |
2237 | for (int i = 0; i < locale_data_count; ++i) { |
2238 | const QLocaleData &item = locale_data[i]; |
2239 | |
2240 | const QString testName = QLatin1String("data_" ) + QString::number(i) + QLatin1String(" (" ) |
2241 | + QLocale::languageToString(language: (QLocale::Language)item.m_language_id) |
2242 | + QLatin1Char('/') + QLocale::countryToString(country: (QLocale::Country)item.m_country_id) |
2243 | + QLatin1Char(')'); |
2244 | QTest::newRow(dataTag: testName.toLatin1().constData()) << (int)item.m_language_id << (int)item.m_country_id; |
2245 | } |
2246 | } |
2247 | |
2248 | void tst_QLocale::testNames() |
2249 | { |
2250 | QFETCH(int, language); |
2251 | QFETCH(int, country); |
2252 | |
2253 | QLocale l1((QLocale::Language)language, (QLocale::Country)country); |
2254 | if (language == QLocale::AnyLanguage && country == QLocale::AnyCountry) |
2255 | language = QLocale::C; |
2256 | QCOMPARE((int)l1.language(), language); |
2257 | QCOMPARE((int)l1.country(), country); |
2258 | |
2259 | QString name = l1.name(); |
2260 | |
2261 | QLocale l2(name); |
2262 | QCOMPARE((int)l2.language(), language); |
2263 | QCOMPARE((int)l2.country(), country); |
2264 | QCOMPARE(l2.name(), name); |
2265 | |
2266 | QLocale l3(name + QLatin1String("@foo" )); |
2267 | QCOMPARE((int)l3.language(), language); |
2268 | QCOMPARE((int)l3.country(), country); |
2269 | QCOMPARE(l3.name(), name); |
2270 | |
2271 | QLocale l4(name + QLatin1String(".foo" )); |
2272 | QCOMPARE((int)l4.language(), language); |
2273 | QCOMPARE((int)l4.country(), country); |
2274 | QCOMPARE(l4.name(), name); |
2275 | |
2276 | if (language != QLocale::C) { |
2277 | int idx = name.indexOf(c: QLatin1Char('_')); |
2278 | QVERIFY(idx != -1); |
2279 | QString lang = name.left(n: idx); |
2280 | |
2281 | QCOMPARE((int)QLocale(lang).language(), language); |
2282 | QCOMPARE((int)QLocale(lang + QLatin1String("@foo" )).language(), language); |
2283 | QCOMPARE((int)QLocale(lang + QLatin1String(".foo" )).language(), language); |
2284 | } |
2285 | } |
2286 | |
2287 | void tst_QLocale::dayName_data() |
2288 | { |
2289 | QTest::addColumn<QString>(name: "locale_name" ); |
2290 | QTest::addColumn<QString>(name: "dayName" ); |
2291 | QTest::addColumn<int>(name: "day" ); |
2292 | QTest::addColumn<QLocale::FormatType>(name: "format" ); |
2293 | |
2294 | QTest::newRow(dataTag: "no_NO" ) << QString("no_NO" ) << QString("tirsdag" ) << 2 << QLocale::LongFormat; |
2295 | QTest::newRow(dataTag: "nb_NO" ) << QString("nb_NO" ) << QString("tirsdag" ) << 2 << QLocale::LongFormat; |
2296 | QTest::newRow(dataTag: "nn_NO" ) << QString("nn_NO" ) << QString("tysdag" ) << 2 << QLocale::LongFormat; |
2297 | |
2298 | QTest::newRow(dataTag: "C long" ) << QString("C" ) << QString("Sunday" ) << 7 << QLocale::LongFormat; |
2299 | QTest::newRow(dataTag: "C short" ) << QString("C" ) << QString("Sun" ) << 7 << QLocale::ShortFormat; |
2300 | QTest::newRow(dataTag: "C narrow" ) << QString("C" ) << QString("7" ) << 7 << QLocale::NarrowFormat; |
2301 | |
2302 | QTest::newRow(dataTag: "ru_RU long" ) |
2303 | << QString("ru_RU" ) |
2304 | << QString::fromUtf8(str: "\320\262\320\276\321\201\320\272\321\200\320" |
2305 | "\265\321\201\320\265\320\275\321\214\320\265" ) |
2306 | << 7 << QLocale::LongFormat; |
2307 | QTest::newRow(dataTag: "ru_RU short" ) |
2308 | << QString("ru_RU" ) << QString::fromUtf8(str: "\320\262\321\201" ) << 7 << QLocale::ShortFormat; |
2309 | QTest::newRow(dataTag: "ru_RU narrow" ) |
2310 | << QString("ru_RU" ) << QString::fromUtf8(str: "\320\262\321\201" ) << 7 << QLocale::NarrowFormat; |
2311 | } |
2312 | |
2313 | void tst_QLocale::dayName() |
2314 | { |
2315 | QFETCH(QString, locale_name); |
2316 | QFETCH(QString, dayName); |
2317 | QFETCH(int, day); |
2318 | QFETCH(QLocale::FormatType, format); |
2319 | |
2320 | QLocale l(locale_name); |
2321 | QCOMPARE(l.dayName(day, format), dayName); |
2322 | |
2323 | QLocale ir("ga_IE" ); |
2324 | QCOMPARE(ir.dayName(1, QLocale::ShortFormat), QLatin1String("Luan" )); |
2325 | QCOMPARE(ir.dayName(7, QLocale::ShortFormat), QLatin1String("Domh" )); |
2326 | |
2327 | QLocale gr("el_GR" ); |
2328 | QCOMPARE(gr.dayName(2, QLocale::ShortFormat), QString::fromUtf8("\316\244\317\201\316\257" )); |
2329 | QCOMPARE(gr.dayName(4, QLocale::ShortFormat), QString::fromUtf8("\316\240\316\255\316\274" )); |
2330 | QCOMPARE(gr.dayName(6, QLocale::ShortFormat), QString::fromUtf8("\316\243\316\254\316\262" )); |
2331 | } |
2332 | |
2333 | void tst_QLocale::standaloneDayName_data() |
2334 | { |
2335 | QTest::addColumn<QString>(name: "locale_name" ); |
2336 | QTest::addColumn<QString>(name: "dayName" ); |
2337 | QTest::addColumn<int>(name: "day" ); |
2338 | QTest::addColumn<QLocale::FormatType>(name: "format" ); |
2339 | |
2340 | QTest::newRow(dataTag: "no_NO" ) << QString("no_NO" ) << QString("tirsdag" ) << 2 << QLocale::LongFormat; |
2341 | QTest::newRow(dataTag: "nb_NO" ) << QString("nb_NO" ) << QString("tirsdag" ) << 2 << QLocale::LongFormat; |
2342 | QTest::newRow(dataTag: "nn_NO" ) << QString("nn_NO" ) << QString("tysdag" ) << 2 << QLocale::LongFormat; |
2343 | |
2344 | QTest::newRow(dataTag: "C invalid: 0 long" ) << QString("C" ) << QString() << 0 << QLocale::LongFormat; |
2345 | QTest::newRow(dataTag: "C invalid: 0 short" ) << QString("C" ) << QString() << 0 << QLocale::ShortFormat; |
2346 | QTest::newRow(dataTag: "C invalid: 0 narrow" ) << QString("C" ) << QString() << 0 << QLocale::NarrowFormat; |
2347 | QTest::newRow(dataTag: "C invalid: 8 long" ) << QString("C" ) << QString() << 8 << QLocale::LongFormat; |
2348 | QTest::newRow(dataTag: "C invalid: 8 short" ) << QString("C" ) << QString() << 8 << QLocale::ShortFormat; |
2349 | QTest::newRow(dataTag: "C invalid: 8 narrow" ) << QString("C" ) << QString() << 8 << QLocale::NarrowFormat; |
2350 | |
2351 | QTest::newRow(dataTag: "C long" ) << QString("C" ) << QString("Sunday" ) << 7 << QLocale::LongFormat; |
2352 | QTest::newRow(dataTag: "C short" ) << QString("C" ) << QString("Sun" ) << 7 << QLocale::ShortFormat; |
2353 | QTest::newRow(dataTag: "C narrow" ) << QString("C" ) << QString("S" ) << 7 << QLocale::NarrowFormat; |
2354 | |
2355 | QTest::newRow(dataTag: "ru_RU long" ) |
2356 | << QString("ru_RU" ) |
2357 | << QString::fromUtf8(str: "\320\262\320\276\321\201\320\272\321\200\320" |
2358 | "\265\321\201\320\265\320\275\321\214\320\265" ) |
2359 | << 7 << QLocale::LongFormat; |
2360 | QTest::newRow(dataTag: "ru_RU short" ) |
2361 | << QString("ru_RU" ) << QString::fromUtf8(str: "\320\262\321\201" ) << 7 << QLocale::ShortFormat; |
2362 | QTest::newRow(dataTag: "ru_RU narrow" ) |
2363 | << QString("ru_RU" ) << QString::fromUtf8(str: "\320\222" ) << 7 << QLocale::NarrowFormat; |
2364 | } |
2365 | |
2366 | void tst_QLocale::standaloneDayName() |
2367 | { |
2368 | QFETCH(QString, locale_name); |
2369 | QFETCH(QString, dayName); |
2370 | QFETCH(int, day); |
2371 | QFETCH(QLocale::FormatType, format); |
2372 | |
2373 | QLocale l(locale_name); |
2374 | QCOMPARE(l.standaloneDayName(day, format), dayName); |
2375 | } |
2376 | |
2377 | void tst_QLocale::underflowOverflow() |
2378 | { |
2379 | QString a(QLatin1String("0." ) + QString(546, QLatin1Char('0')) + QLatin1String("1e10" )); |
2380 | bool ok = false; |
2381 | double d = a.toDouble(ok: &ok); |
2382 | QVERIFY(!ok); |
2383 | QCOMPARE(d, 0.0); |
2384 | |
2385 | a = QLatin1String("1e600" ); |
2386 | ok = false; |
2387 | d = a.toDouble(ok: &ok); |
2388 | QVERIFY(!ok); // detectable overflow |
2389 | QVERIFY(qIsInf(d)); |
2390 | |
2391 | a = QLatin1String("-1e600" ); |
2392 | ok = false; |
2393 | d = a.toDouble(ok: &ok); |
2394 | QVERIFY(!ok); // detectable underflow |
2395 | QVERIFY(qIsInf(-d)); |
2396 | |
2397 | a = QLatin1String("1e-600" ); |
2398 | ok = false; |
2399 | d = a.toDouble(ok: &ok); |
2400 | QVERIFY(!ok); |
2401 | QCOMPARE(d, 0.0); |
2402 | |
2403 | a = QLatin1String("-9223372036854775809" ); |
2404 | a.toLongLong(ok: &ok); |
2405 | QVERIFY(!ok); |
2406 | } |
2407 | |
2408 | void tst_QLocale::defaultNumberingSystem_data() |
2409 | { |
2410 | QTest::addColumn<QString>(name: "expect" ); |
2411 | |
2412 | QTest::newRow(dataTag: "sk_SK" ) << QStringLiteral("123" ); |
2413 | QTest::newRow(dataTag: "ta_IN" ) << QStringLiteral("123" ); |
2414 | QTest::newRow(dataTag: "te_IN" ) << QStringLiteral("123" ); |
2415 | QTest::newRow(dataTag: "hi_IN" ) << QStringLiteral("123" ); |
2416 | QTest::newRow(dataTag: "gu_IN" ) << QStringLiteral("123" ); |
2417 | QTest::newRow(dataTag: "kn_IN" ) << QStringLiteral("123" ); |
2418 | QTest::newRow(dataTag: "pa_IN" ) << QStringLiteral("123" ); |
2419 | QTest::newRow(dataTag: "ne_IN" ) << QString::fromUtf8(str: "१२३" ); |
2420 | QTest::newRow(dataTag: "mr_IN" ) << QString::fromUtf8(str: "१२३" ); |
2421 | QTest::newRow(dataTag: "ml_IN" ) << QStringLiteral("123" ); |
2422 | QTest::newRow(dataTag: "kok_IN" ) << QStringLiteral("123" ); |
2423 | } |
2424 | |
2425 | void tst_QLocale::defaultNumberingSystem() |
2426 | { |
2427 | QFETCH(QString, expect); |
2428 | QLatin1String name(QTest::currentDataTag()); |
2429 | QLocale locale(name); |
2430 | QCOMPARE(locale.toString(123), expect); |
2431 | } |
2432 | |
2433 | void tst_QLocale::ampm_data() |
2434 | { |
2435 | QTest::addColumn<QString>(name: "morn" ); |
2436 | QTest::addColumn<QString>(name: "even" ); |
2437 | |
2438 | QTest::newRow(dataTag: "C" ) << QStringLiteral("AM" ) << QStringLiteral("PM" ); |
2439 | QTest::newRow(dataTag: "de_DE" ) << QStringLiteral("AM" ) << QStringLiteral("PM" ); |
2440 | QTest::newRow(dataTag: "sv_SE" ) << QStringLiteral("fm" ) << QStringLiteral("em" ); |
2441 | QTest::newRow(dataTag: "nl_NL" ) << QStringLiteral("a.m." ) << QStringLiteral("p.m." ); |
2442 | QTest::newRow(dataTag: "uk_UA" ) << QString::fromUtf8(str: "\320\264\320\277" ) |
2443 | << QString::fromUtf8(str: "\320\277\320\277" ); |
2444 | QTest::newRow(dataTag: "tr_TR" ) << QString::fromUtf8(str: "\303\226\303\226" ) |
2445 | << QString::fromUtf8(str: "\303\226\123" ); |
2446 | QTest::newRow(dataTag: "id_ID" ) << QStringLiteral("AM" ) << QStringLiteral("PM" ); |
2447 | QTest::newRow(dataTag: "ta_LK" ) << QString::fromUtf8(str: "முற்பகல்" ) << QString::fromUtf8(str: "பிற்பகல்" ); |
2448 | } |
2449 | |
2450 | void tst_QLocale::ampm() |
2451 | { |
2452 | QFETCH(QString, morn); |
2453 | QFETCH(QString, even); |
2454 | QLatin1String name(QTest::currentDataTag()); |
2455 | QLocale locale(name == QLatin1String("C" ) ? QLocale(QLocale::C) : QLocale(name)); |
2456 | QCOMPARE(locale.amText(), morn); |
2457 | QCOMPARE(locale.pmText(), even); |
2458 | } |
2459 | |
2460 | void tst_QLocale::dateFormat() |
2461 | { |
2462 | const QLocale c(QLocale::C); |
2463 | // check that the NarrowFormat is the same as ShortFormat. |
2464 | QCOMPARE(c.dateFormat(QLocale::NarrowFormat), c.dateFormat(QLocale::ShortFormat)); |
2465 | |
2466 | const QLocale no("no_NO" ); |
2467 | QCOMPARE(no.dateFormat(QLocale::NarrowFormat), QLatin1String("dd.MM.yyyy" )); |
2468 | QCOMPARE(no.dateFormat(QLocale::ShortFormat), QLatin1String("dd.MM.yyyy" )); |
2469 | QCOMPARE(no.dateFormat(QLocale::LongFormat), QLatin1String("dddd d. MMMM yyyy" )); |
2470 | |
2471 | const QLocale ca("en_CA" ); |
2472 | QCOMPARE(ca.dateFormat(QLocale::ShortFormat), QLatin1String("yyyy-MM-dd" )); |
2473 | QCOMPARE(ca.dateFormat(QLocale::LongFormat), QLatin1String("dddd, MMMM d, yyyy" )); |
2474 | |
2475 | const QLocale ja("ja_JP" ); |
2476 | QCOMPARE(ja.dateFormat(QLocale::ShortFormat), QLatin1String("yyyy/MM/dd" )); |
2477 | |
2478 | const QLocale ir("ga_IE" ); |
2479 | QCOMPARE(ir.dateFormat(QLocale::ShortFormat), QLatin1String("dd/MM/yyyy" )); |
2480 | |
2481 | const auto sys = QLocale::system(); // QTBUG-92018, ru_RU on MS |
2482 | const QDate date(2021, 3, 17); |
2483 | QCOMPARE(sys.toString(date, sys.dateFormat(QLocale::LongFormat)), sys.toString(date)); |
2484 | } |
2485 | |
2486 | void tst_QLocale::timeFormat() |
2487 | { |
2488 | const QLocale c(QLocale::C); |
2489 | // check that the NarrowFormat is the same as ShortFormat. |
2490 | QCOMPARE(c.timeFormat(QLocale::NarrowFormat), c.timeFormat(QLocale::ShortFormat)); |
2491 | |
2492 | const QLocale no("no_NO" ); |
2493 | QCOMPARE(no.timeFormat(QLocale::NarrowFormat), QLatin1String("HH:mm" )); |
2494 | QCOMPARE(no.timeFormat(QLocale::ShortFormat), QLatin1String("HH:mm" )); |
2495 | QCOMPARE(no.timeFormat(QLocale::LongFormat), QLatin1String("HH:mm:ss t" )); |
2496 | |
2497 | const QLocale id("id_ID" ); |
2498 | QCOMPARE(id.timeFormat(QLocale::ShortFormat), QLatin1String("HH.mm" )); |
2499 | QCOMPARE(id.timeFormat(QLocale::LongFormat), QLatin1String("HH.mm.ss t" )); |
2500 | |
2501 | const QLocale cat("ca_ES" ); |
2502 | QCOMPARE(cat.timeFormat(QLocale::ShortFormat), QLatin1String("H:mm" )); |
2503 | QCOMPARE(cat.timeFormat(QLocale::LongFormat), QLatin1String("H:mm:ss (t)" )); |
2504 | |
2505 | const QLocale bra("pt_BR" ); |
2506 | QCOMPARE(bra.timeFormat(QLocale::ShortFormat), QLatin1String("HH:mm" )); |
2507 | QCOMPARE(bra.timeFormat(QLocale::LongFormat), QLatin1String("HH:mm:ss t" )); |
2508 | } |
2509 | |
2510 | void tst_QLocale::dateTimeFormat() |
2511 | { |
2512 | const QLocale c(QLocale::C); |
2513 | // check that the NarrowFormat is the same as ShortFormat. |
2514 | QCOMPARE(c.dateTimeFormat(QLocale::NarrowFormat), c.dateTimeFormat(QLocale::ShortFormat)); |
2515 | |
2516 | const QLocale no("no_NO" ); |
2517 | QCOMPARE(no.dateTimeFormat(QLocale::NarrowFormat), QLatin1String("dd.MM.yyyy HH:mm" )); |
2518 | QCOMPARE(no.dateTimeFormat(QLocale::ShortFormat), QLatin1String("dd.MM.yyyy HH:mm" )); |
2519 | QCOMPARE(no.dateTimeFormat(QLocale::LongFormat), QLatin1String("dddd d. MMMM yyyy HH:mm:ss t" )); |
2520 | } |
2521 | |
2522 | void tst_QLocale::monthName() |
2523 | { |
2524 | const QLocale c(QLocale::C); |
2525 | QCOMPARE(c.monthName(0, QLocale::ShortFormat), QString()); |
2526 | QCOMPARE(c.monthName(0, QLocale::LongFormat), QString()); |
2527 | QCOMPARE(c.monthName(0, QLocale::NarrowFormat), QString()); |
2528 | QCOMPARE(c.monthName(13, QLocale::ShortFormat), QString()); |
2529 | QCOMPARE(c.monthName(13, QLocale::LongFormat), QString()); |
2530 | QCOMPARE(c.monthName(13, QLocale::NarrowFormat), QString()); |
2531 | |
2532 | QCOMPARE(c.monthName(1, QLocale::LongFormat), QLatin1String("January" )); |
2533 | QCOMPARE(c.monthName(1, QLocale::ShortFormat), QLatin1String("Jan" )); |
2534 | QCOMPARE(c.monthName(1, QLocale::NarrowFormat), QLatin1String("1" )); |
2535 | |
2536 | const QLocale de("de_DE" ); |
2537 | QCOMPARE(de.monthName(12, QLocale::LongFormat), QLatin1String("Dezember" )); |
2538 | QCOMPARE(de.monthName(12, QLocale::ShortFormat), QLatin1String("Dez." )); |
2539 | // 'de' locale doesn't have narrow month name |
2540 | QCOMPARE(de.monthName(12, QLocale::NarrowFormat), QLatin1String("D" )); |
2541 | |
2542 | const QLocale ru("ru_RU" ); |
2543 | QCOMPARE(ru.monthName(1, QLocale::LongFormat), |
2544 | QString::fromUtf8("\321\217\320\275\320\262\320\260\321\200\321\217" )); |
2545 | QCOMPARE(ru.monthName(1, QLocale::ShortFormat), |
2546 | QString::fromUtf8("\321\217\320\275\320\262\56" )); |
2547 | QCOMPARE(ru.monthName(1, QLocale::NarrowFormat), QString::fromUtf8("\320\257" )); |
2548 | const auto sys = QLocale::system(); |
2549 | if (sys.language() == QLocale::Russian) // QTBUG-92018 |
2550 | QVERIFY(sys.monthName(3) != sys.standaloneMonthName(3)); |
2551 | |
2552 | const QLocale ir("ga_IE" ); |
2553 | QCOMPARE(ir.monthName(1, QLocale::ShortFormat), QLatin1String("Ean" )); |
2554 | QCOMPARE(ir.monthName(12, QLocale::ShortFormat), QLatin1String("Noll" )); |
2555 | |
2556 | const QLocale cz("cs_CZ" ); |
2557 | QCOMPARE(cz.monthName(1, QLocale::ShortFormat), QLatin1String("led" )); |
2558 | QCOMPARE(cz.monthName(12, QLocale::ShortFormat), QLatin1String("pro" )); |
2559 | } |
2560 | |
2561 | void tst_QLocale::standaloneMonthName() |
2562 | { |
2563 | const QLocale c(QLocale::C); |
2564 | QCOMPARE(c.monthName(0, QLocale::ShortFormat), QString()); |
2565 | QCOMPARE(c.monthName(0, QLocale::LongFormat), QString()); |
2566 | QCOMPARE(c.monthName(0, QLocale::NarrowFormat), QString()); |
2567 | QCOMPARE(c.monthName(13, QLocale::ShortFormat), QString()); |
2568 | QCOMPARE(c.monthName(13, QLocale::LongFormat), QString()); |
2569 | QCOMPARE(c.monthName(13, QLocale::NarrowFormat), QString()); |
2570 | |
2571 | QCOMPARE(c.standaloneMonthName(1, QLocale::LongFormat), QLatin1String("January" )); |
2572 | QCOMPARE(c.standaloneMonthName(1, QLocale::ShortFormat), QLatin1String("Jan" )); |
2573 | |
2574 | const QLocale de("de_DE" ); |
2575 | // For de_DE locale Unicode CLDR database doesn't contain standalone long months |
2576 | // so just checking if the return value is the same as in monthName(). |
2577 | QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat), QLatin1String("Dezember" )); |
2578 | QCOMPARE(de.standaloneMonthName(12, QLocale::LongFormat), |
2579 | de.monthName(12, QLocale::LongFormat)); |
2580 | QCOMPARE(de.standaloneMonthName(12, QLocale::ShortFormat), QLatin1String("Dez" )); |
2581 | QCOMPARE(de.standaloneMonthName(12, QLocale::NarrowFormat), QLatin1String("D" )); |
2582 | |
2583 | QLocale ru("ru_RU" ); |
2584 | QCOMPARE(ru.standaloneMonthName(1, QLocale::LongFormat), |
2585 | QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2\xd0\xb0\xd1\x80\xd1\x8c" )); |
2586 | QCOMPARE(ru.standaloneMonthName(1, QLocale::ShortFormat), |
2587 | QString::fromUtf8("\xd1\x8f\xd0\xbd\xd0\xb2." )); |
2588 | QCOMPARE(ru.standaloneMonthName(1, QLocale::NarrowFormat), QString::fromUtf8("\xd0\xaf" )); |
2589 | } |
2590 | |
2591 | void tst_QLocale::currency() |
2592 | { |
2593 | const QLocale c(QLocale::C); |
2594 | QCOMPARE(c.toCurrencyString(qulonglong(1234)), QString("1234" )); |
2595 | QCOMPARE(c.toCurrencyString(qlonglong(-1234)), QString("-1234" )); |
2596 | QCOMPARE(c.toCurrencyString(double(1234.56)), QString("1234.56" )); |
2597 | QCOMPARE(c.toCurrencyString(double(-1234.56)), QString("-1234.56" )); |
2598 | QCOMPARE(c.toCurrencyString(double(-1234.5678)), QString("-1234.57" )); |
2599 | QCOMPARE(c.toCurrencyString(double(-1234.5678), NULL, 4), QString("-1234.5678" )); |
2600 | QCOMPARE(c.toCurrencyString(double(-1234.56), NULL, 4), QString("-1234.5600" )); |
2601 | |
2602 | const QLocale en_US("en_US" ); |
2603 | QCOMPARE(en_US.toCurrencyString(qulonglong(1234)), QString("$1,234" )); |
2604 | QCOMPARE(en_US.toCurrencyString(qlonglong(-1234)), QString("($1,234)" )); |
2605 | QCOMPARE(en_US.toCurrencyString(double(1234.56)), QString("$1,234.56" )); |
2606 | QCOMPARE(en_US.toCurrencyString(double(-1234.56)), QString("($1,234.56)" )); |
2607 | QCOMPARE(en_US.toCurrencyString(double(-1234.5678)), QString("($1,234.57)" )); |
2608 | QCOMPARE(en_US.toCurrencyString(double(-1234.5678), NULL, 4), QString("($1,234.5678)" )); |
2609 | QCOMPARE(en_US.toCurrencyString(double(-1234.56), NULL, 4), QString("($1,234.5600)" )); |
2610 | |
2611 | const QLocale ru_RU("ru_RU" ); |
2612 | QCOMPARE(ru_RU.toCurrencyString(qulonglong(1234)), |
2613 | QString::fromUtf8("1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd" )); |
2614 | QCOMPARE(ru_RU.toCurrencyString(qlonglong(-1234)), |
2615 | QString::fromUtf8("-1" "\xc2\xa0" "234\xc2\xa0\xe2\x82\xbd" )); |
2616 | QCOMPARE(ru_RU.toCurrencyString(double(1234.56)), |
2617 | QString::fromUtf8("1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd" )); |
2618 | QCOMPARE(ru_RU.toCurrencyString(double(-1234.56)), |
2619 | QString::fromUtf8("-1" "\xc2\xa0" "234,56\xc2\xa0\xe2\x82\xbd" )); |
2620 | |
2621 | const QLocale de_DE("de_DE" ); |
2622 | QCOMPARE(de_DE.toCurrencyString(qulonglong(1234)), |
2623 | QString::fromUtf8("1.234\xc2\xa0\xe2\x82\xac" )); |
2624 | QCOMPARE(de_DE.toCurrencyString(qulonglong(1234), QLatin1String("BAZ" )), |
2625 | QString::fromUtf8("1.234\xc2\xa0" "BAZ" )); |
2626 | QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234)), |
2627 | QString::fromUtf8("-1.234\xc2\xa0\xe2\x82\xac" )); |
2628 | QCOMPARE(de_DE.toCurrencyString(qlonglong(-1234), QLatin1String("BAZ" )), |
2629 | QString::fromUtf8("-1.234\xc2\xa0" "BAZ" )); |
2630 | QCOMPARE(de_DE.toCurrencyString(double(1234.56)), |
2631 | QString::fromUtf8("1.234,56\xc2\xa0\xe2\x82\xac" )); |
2632 | QCOMPARE(de_DE.toCurrencyString(double(-1234.56)), |
2633 | QString::fromUtf8("-1.234,56\xc2\xa0\xe2\x82\xac" )); |
2634 | QCOMPARE(de_DE.toCurrencyString(double(-1234.56), QLatin1String("BAZ" )), |
2635 | QString::fromUtf8("-1.234,56\xc2\xa0" "BAZ" )); |
2636 | |
2637 | const QLocale es_CR(QLocale::Spanish, QLocale::CostaRica); |
2638 | QCOMPARE(es_CR.toCurrencyString(double(1565.25)), |
2639 | QString::fromUtf8("\xE2\x82\xA1" "1\xC2\xA0" "565,25" )); |
2640 | QCOMPARE(es_CR.toCurrencyString(double(12565.25)), |
2641 | QString::fromUtf8("\xE2\x82\xA1" "12\xC2\xA0" "565,25" )); |
2642 | |
2643 | const QLocale system = QLocale::system(); |
2644 | QVERIFY(system.toCurrencyString(1, QLatin1String("FOO" )).contains(QLatin1String("FOO" ))); |
2645 | } |
2646 | |
2647 | void tst_QLocale::quoteString() |
2648 | { |
2649 | const QString someText("text" ); |
2650 | const QLocale c(QLocale::C); |
2651 | QCOMPARE(c.quoteString(someText), QString::fromUtf8("\x22" "text" "\x22" )); |
2652 | QCOMPARE(c.quoteString(someText, QLocale::AlternateQuotation), |
2653 | QString::fromUtf8("\x27" "text" "\x27" )); |
2654 | |
2655 | const QLocale de_CH("de_CH" ); |
2656 | QCOMPARE(de_CH.quoteString(someText), QString::fromUtf8("\xe2\x80\x9e" "text" "\xe2\x80\x9c" )); |
2657 | QCOMPARE(de_CH.quoteString(someText, QLocale::AlternateQuotation), |
2658 | QString::fromUtf8("\xe2\x80\x9a" "text" "\xe2\x80\x98" )); |
2659 | |
2660 | } |
2661 | |
2662 | void tst_QLocale::uiLanguages() |
2663 | { |
2664 | const QLocale c(QLocale::C); |
2665 | QCOMPARE(c.uiLanguages().size(), 1); |
2666 | QCOMPARE(c.uiLanguages().at(0), QLatin1String("C" )); |
2667 | |
2668 | const QLocale en_US("en_US" ); |
2669 | QCOMPARE(en_US.uiLanguages().size(), 3); |
2670 | QCOMPARE(en_US.uiLanguages().at(0), QLatin1String("en" )); |
2671 | QCOMPARE(en_US.uiLanguages().at(1), QLatin1String("en-US" )); |
2672 | QCOMPARE(en_US.uiLanguages().at(2), QLatin1String("en-Latn-US" )); |
2673 | |
2674 | const QLocale en_Latn_US("en_Latn_US" ); |
2675 | QCOMPARE(en_Latn_US.uiLanguages().size(), 3); |
2676 | QCOMPARE(en_Latn_US.uiLanguages().at(0), QLatin1String("en" )); |
2677 | QCOMPARE(en_Latn_US.uiLanguages().at(1), QLatin1String("en-US" )); |
2678 | QCOMPARE(en_Latn_US.uiLanguages().at(2), QLatin1String("en-Latn-US" )); |
2679 | |
2680 | const QLocale en_GB("en_GB" ); |
2681 | QCOMPARE(en_GB.uiLanguages().size(), 2); |
2682 | QCOMPARE(en_GB.uiLanguages().at(0), QLatin1String("en-GB" )); |
2683 | QCOMPARE(en_GB.uiLanguages().at(1), QLatin1String("en-Latn-GB" )); |
2684 | |
2685 | const QLocale en_Dsrt_US("en_Dsrt_US" ); |
2686 | QCOMPARE(en_Dsrt_US.uiLanguages().size(), 2); |
2687 | QCOMPARE(en_Dsrt_US.uiLanguages().at(0), QLatin1String("en-Dsrt" )); |
2688 | QCOMPARE(en_Dsrt_US.uiLanguages().at(1), QLatin1String("en-Dsrt-US" )); |
2689 | |
2690 | const QLocale ru_RU("ru_RU" ); |
2691 | QCOMPARE(ru_RU.uiLanguages().size(), 3); |
2692 | QCOMPARE(ru_RU.uiLanguages().at(0), QLatin1String("ru" )); |
2693 | QCOMPARE(ru_RU.uiLanguages().at(1), QLatin1String("ru-RU" )); |
2694 | QCOMPARE(ru_RU.uiLanguages().at(2), QLatin1String("ru-Cyrl-RU" )); |
2695 | |
2696 | const QLocale zh_Hant("zh_Hant" ); |
2697 | QCOMPARE(zh_Hant.uiLanguages().size(), 2); |
2698 | QCOMPARE(zh_Hant.uiLanguages().at(0), QLatin1String("zh-TW" )); |
2699 | QCOMPARE(zh_Hant.uiLanguages().at(1), QLatin1String("zh-Hant-TW" )); |
2700 | } |
2701 | |
2702 | void tst_QLocale::weekendDays() |
2703 | { |
2704 | const QLocale c(QLocale::C); |
2705 | QList<Qt::DayOfWeek> days; |
2706 | days << Qt::Monday << Qt::Tuesday << Qt::Wednesday << Qt::Thursday << Qt::Friday; |
2707 | QCOMPARE(c.weekdays(), days); |
2708 | } |
2709 | |
2710 | void tst_QLocale::listPatterns() |
2711 | { |
2712 | QStringList sl1; |
2713 | QStringList sl2; |
2714 | sl2 << "aaa" ; |
2715 | QStringList sl3; |
2716 | sl3 << "aaa" << "bbb" ; |
2717 | QStringList sl4; |
2718 | sl4 << "aaa" << "bbb" << "ccc" ; |
2719 | QStringList sl5; |
2720 | sl5 << "aaa" << "bbb" << "ccc" << "ddd" ; |
2721 | |
2722 | const QLocale c(QLocale::C); |
2723 | QCOMPARE(c.createSeparatedList(sl1), QString("" )); |
2724 | QCOMPARE(c.createSeparatedList(sl2), QString("aaa" )); |
2725 | QCOMPARE(c.createSeparatedList(sl3), QString("aaa, bbb" )); |
2726 | QCOMPARE(c.createSeparatedList(sl4), QString("aaa, bbb, ccc" )); |
2727 | QCOMPARE(c.createSeparatedList(sl5), QString("aaa, bbb, ccc, ddd" )); |
2728 | |
2729 | const QLocale en_US("en_US" ); |
2730 | QCOMPARE(en_US.createSeparatedList(sl1), QString("" )); |
2731 | QCOMPARE(en_US.createSeparatedList(sl2), QString("aaa" )); |
2732 | QCOMPARE(en_US.createSeparatedList(sl3), QString("aaa and bbb" )); |
2733 | QCOMPARE(en_US.createSeparatedList(sl4), QString("aaa, bbb, and ccc" )); |
2734 | QCOMPARE(en_US.createSeparatedList(sl5), QString("aaa, bbb, ccc, and ddd" )); |
2735 | |
2736 | const QLocale zh_CN("zh_CN" ); |
2737 | QCOMPARE(zh_CN.createSeparatedList(sl1), QString("" )); |
2738 | QCOMPARE(zh_CN.createSeparatedList(sl2), QString("aaa" )); |
2739 | QCOMPARE(zh_CN.createSeparatedList(sl3), QString::fromUtf8("aaa" "\xe5\x92\x8c" "bbb" )); |
2740 | QCOMPARE(zh_CN.createSeparatedList(sl4), |
2741 | QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe5\x92\x8c" "ccc" )); |
2742 | QCOMPARE(zh_CN.createSeparatedList(sl5), |
2743 | QString::fromUtf8("aaa" "\xe3\x80\x81" "bbb" "\xe3\x80\x81" |
2744 | "ccc" "\xe5\x92\x8c" "ddd" )); |
2745 | } |
2746 | |
2747 | void tst_QLocale::measurementSystems_data() |
2748 | { |
2749 | QTest::addColumn<QLocale>(name: "locale" ); |
2750 | QTest::addColumn<QLocale::MeasurementSystem>(name: "system" ); |
2751 | QTest::newRow(dataTag: "en_US" ) << QLocale(QLocale::English, QLocale::UnitedStates) << QLocale::ImperialUSSystem; |
2752 | QTest::newRow(dataTag: "en_GB" ) << QLocale(QLocale::English, QLocale::UnitedKingdom) << QLocale::ImperialUKSystem; |
2753 | QTest::newRow(dataTag: "en_AU" ) << QLocale(QLocale::English, QLocale::Australia) << QLocale::MetricSystem; |
2754 | QTest::newRow(dataTag: "de" ) << QLocale(QLocale::German) << QLocale::MetricSystem; |
2755 | } |
2756 | |
2757 | void tst_QLocale::measurementSystems() |
2758 | { |
2759 | QFETCH(QLocale, locale); |
2760 | QFETCH(QLocale::MeasurementSystem, system); |
2761 | QCOMPARE(locale.measurementSystem(), system); |
2762 | } |
2763 | |
2764 | void tst_QLocale::QTBUG_26035_positivesign() |
2765 | { |
2766 | QLocale locale(QLocale::C); |
2767 | bool ok (false); |
2768 | QCOMPARE(locale.toInt(QString("+100,000" ), &ok), 100000); |
2769 | QVERIFY(ok); |
2770 | ok = false; |
2771 | QCOMPARE(locale.toInt(QString("+100,000,000" ), &ok), 100000000); |
2772 | QVERIFY(ok); |
2773 | ok = false; |
2774 | QCOMPARE(locale.toLongLong(QString("+100,000" ), &ok), (qlonglong)100000); |
2775 | QVERIFY(ok); |
2776 | ok = false; |
2777 | QCOMPARE(locale.toLongLong(QString("+100,000,000" ), &ok), (qlonglong)100000000); |
2778 | QVERIFY(ok); |
2779 | } |
2780 | |
2781 | void tst_QLocale::textDirection_data() |
2782 | { |
2783 | QTest::addColumn<int>(name: "language" ); |
2784 | QTest::addColumn<int>(name: "script" ); |
2785 | QTest::addColumn<bool>(name: "rightToLeft" ); |
2786 | |
2787 | for (int language = QLocale::C; language <= QLocale::LastLanguage; ++language) { |
2788 | bool rightToLeft = false; |
2789 | switch (language) { |
2790 | // based on likelySubtags for RTL scripts |
2791 | #if QT_DEPRECATED_SINCE(5, 15) |
2792 | case QLocale::AncientNorthArabian: |
2793 | case QLocale::ClassicalMandaic: |
2794 | case QLocale::Lydian: |
2795 | case QLocale::ManichaeanMiddlePersian: |
2796 | case QLocale::Meroitic: |
2797 | case QLocale::OldTurkish: |
2798 | case QLocale::Parthian: |
2799 | case QLocale::PrakritLanguage: |
2800 | case QLocale::Sabaean: |
2801 | case QLocale::Samaritan: |
2802 | #endif |
2803 | case QLocale::AncientGreek: |
2804 | case QLocale::Arabic: |
2805 | case QLocale::Aramaic: |
2806 | case QLocale::Avestan: |
2807 | case QLocale::CentralKurdish: |
2808 | case QLocale::Divehi: |
2809 | // case QLocale::Fulah: |
2810 | // case QLocale::Hausa: |
2811 | case QLocale::Hebrew: |
2812 | // case QLocale::Hungarian: |
2813 | case QLocale::Kashmiri: |
2814 | // case QLocale::Kurdish: |
2815 | case QLocale::Mandingo: |
2816 | case QLocale::Mazanderani: |
2817 | case QLocale::Mende: |
2818 | case QLocale::Nko: |
2819 | case QLocale::NorthernLuri: |
2820 | case QLocale::Pahlavi: |
2821 | case QLocale::Pashto: |
2822 | case QLocale::Persian: |
2823 | case QLocale::Phoenician: |
2824 | case QLocale::Sindhi: |
2825 | case QLocale::SouthernKurdish: |
2826 | case QLocale::Syriac: |
2827 | case QLocale::Uighur: |
2828 | case QLocale::Urdu: |
2829 | case QLocale::WesternBalochi: |
2830 | case QLocale::Yiddish: |
2831 | // false if there is no locale data for language: |
2832 | rightToLeft = (QLocale(QLocale::Language(language)).language() |
2833 | == QLocale::Language(language)); |
2834 | break; |
2835 | default: |
2836 | break; |
2837 | } |
2838 | const QLatin1String testName = QLocalePrivate::languageToCode(language: QLocale::Language(language)); |
2839 | QTest::newRow(qPrintable(testName)) << language << int(QLocale::AnyScript) << rightToLeft; |
2840 | } |
2841 | QTest::newRow(dataTag: "pa_Arab" ) << int(QLocale::Punjabi) << int(QLocale::ArabicScript) << true; |
2842 | QTest::newRow(dataTag: "uz_Arab" ) << int(QLocale::Uzbek) << int(QLocale::ArabicScript) << true; |
2843 | } |
2844 | |
2845 | void tst_QLocale::textDirection() |
2846 | { |
2847 | QFETCH(int, language); |
2848 | QFETCH(int, script); |
2849 | QFETCH(bool, rightToLeft); |
2850 | |
2851 | QLocale locale(QLocale::Language(language), QLocale::Script(script), QLocale::AnyCountry); |
2852 | QCOMPARE(locale.textDirection() == Qt::RightToLeft, rightToLeft); |
2853 | } |
2854 | |
2855 | void tst_QLocale::formattedDataSize_data() |
2856 | { |
2857 | QTest::addColumn<QLocale::Language>(name: "language" ); |
2858 | QTest::addColumn<int>(name: "decimalPlaces" ); |
2859 | QTest::addColumn<QLocale::DataSizeFormats>(name: "units" ); |
2860 | QTest::addColumn<int>(name: "bytes" ); |
2861 | QTest::addColumn<QString>(name: "output" ); |
2862 | |
2863 | struct { |
2864 | const char *name; |
2865 | QLocale::Language lang; |
2866 | const char *bytes; |
2867 | const char abbrev; |
2868 | const char sep; // decimal separator |
2869 | } data[] = { |
2870 | { .name: "English" , .lang: QLocale::English, .bytes: "bytes" , .abbrev: 'B', .sep: '.' }, |
2871 | { .name: "French" , .lang: QLocale::French, .bytes: "octets" , .abbrev: 'o', .sep: ',' }, |
2872 | { .name: "C" , .lang: QLocale::C, .bytes: "bytes" , .abbrev: 'B', .sep: '.' } |
2873 | }; |
2874 | |
2875 | for (const auto row : data) { |
2876 | #define ROWB(id, deci, num, text) \ |
2877 | QTest::addRow("%s-%s", row.name, id) \ |
2878 | << row.lang << deci << format \ |
2879 | << num << (QString(text) + QChar(' ') + QString(row.bytes)) |
2880 | #define ROWQ(id, deci, num, head, tail) \ |
2881 | QTest::addRow("%s-%s", row.name, id) \ |
2882 | << row.lang << deci << format \ |
2883 | << num << (QString(head) + QChar(row.sep) + QString(tail) + QChar(row.abbrev)) |
2884 | |
2885 | // Metatype system fails to handle raw enum members as format; needs variable |
2886 | { |
2887 | const QLocale::DataSizeFormats format = QLocale::DataSizeIecFormat; |
2888 | ROWB("IEC-0" , 2, 0, "0" ); |
2889 | ROWB("IEC-10" , 2, 10, "10" ); |
2890 | ROWQ("IEC-12Ki" , 2, 12345, "12" , "06 Ki" ); |
2891 | ROWQ("IEC-16Ki" , 2, 16384, "16" , "00 Ki" ); |
2892 | ROWQ("IEC-1235k" , 2, 1234567, "1" , "18 Mi" ); |
2893 | ROWQ("IEC-1374k" , 2, 1374744, "1" , "31 Mi" ); |
2894 | ROWQ("IEC-1234M" , 2, 1234567890, "1" , "15 Gi" ); |
2895 | } |
2896 | { |
2897 | const QLocale::DataSizeFormats format = QLocale::DataSizeTraditionalFormat; |
2898 | ROWB("Trad-0" , 2, 0, "0" ); |
2899 | ROWB("Trad-10" , 2, 10, "10" ); |
2900 | ROWQ("Trad-12Ki" , 2, 12345, "12" , "06 k" ); |
2901 | ROWQ("Trad-16Ki" , 2, 16384, "16" , "00 k" ); |
2902 | ROWQ("Trad-1235k" , 2, 1234567, "1" , "18 M" ); |
2903 | ROWQ("Trad-1374k" , 2, 1374744, "1" , "31 M" ); |
2904 | ROWQ("Trad-1234M" , 2, 1234567890, "1" , "15 G" ); |
2905 | } |
2906 | { |
2907 | const QLocale::DataSizeFormats format = QLocale::DataSizeSIFormat; |
2908 | ROWB("Decimal-0" , 2, 0, "0" ); |
2909 | ROWB("Decimal-10" , 2, 10, "10" ); |
2910 | ROWQ("Decimal-16Ki" , 2, 16384, "16" , "38 k" ); |
2911 | ROWQ("Decimal-1234k" , 2, 1234567, "1" , "23 M" ); |
2912 | ROWQ("Decimal-1374k" , 2, 1374744, "1" , "37 M" ); |
2913 | ROWQ("Decimal-1234M" , 2, 1234567890, "1" , "23 G" ); |
2914 | } |
2915 | #undef ROWQ |
2916 | #undef ROWB |
2917 | } |
2918 | |
2919 | // Languages which don't use a Latin alphabet |
2920 | |
2921 | const QLocale::DataSizeFormats iecFormat = QLocale::DataSizeIecFormat; |
2922 | const QLocale::DataSizeFormats traditionalFormat = QLocale::DataSizeTraditionalFormat; |
2923 | const QLocale::DataSizeFormats siFormat = QLocale::DataSizeSIFormat; |
2924 | const QLocale::Language lang = QLocale::Russian; |
2925 | |
2926 | QTest::newRow(dataTag: "Russian-IEC-0" ) << lang << 2 << iecFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B" ); |
2927 | QTest::newRow(dataTag: "Russian-IEC-10" ) << lang << 2 << iecFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B" ); |
2928 | // CLDR doesn't provide IEC prefixes (yet?) so they aren't getting translated |
2929 | QTest::newRow(dataTag: "Russian-IEC-12Ki" ) << lang << 2 << iecFormat << 12345 << QString("12,06 KiB" ); |
2930 | QTest::newRow(dataTag: "Russian-IEC-16Ki" ) << lang << 2 << iecFormat << 16384 << QString("16,00 KiB" ); |
2931 | QTest::newRow(dataTag: "Russian-IEC-1235k" ) << lang << 2 << iecFormat << 1234567 << QString("1,18 MiB" ); |
2932 | QTest::newRow(dataTag: "Russian-IEC-1374k" ) << lang << 2 << iecFormat << 1374744 << QString("1,31 MiB" ); |
2933 | QTest::newRow(dataTag: "Russian-IEC-1234M" ) << lang << 2 << iecFormat << 1234567890 << QString("1,15 GiB" ); |
2934 | |
2935 | QTest::newRow(dataTag: "Russian-Trad-0" ) << lang << 2 << traditionalFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B" ); |
2936 | QTest::newRow(dataTag: "Russian-Trad-10" ) << lang << 2 << traditionalFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B" ); |
2937 | QTest::newRow(dataTag: "Russian-Trad-12Ki" ) << lang << 2 << traditionalFormat << 12345 << QString("12,06 \u043A\u0411" ); |
2938 | QTest::newRow(dataTag: "Russian-Trad-16Ki" ) << lang << 2 << traditionalFormat << 16384 << QString("16,00 \u043A\u0411" ); |
2939 | QTest::newRow(dataTag: "Russian-Trad-1235k" ) << lang << 2 << traditionalFormat << 1234567 << QString("1,18 \u041C\u0411" ); |
2940 | QTest::newRow(dataTag: "Russian-Trad-1374k" ) << lang << 2 << traditionalFormat << 1374744 << QString("1,31 \u041C\u0411" ); |
2941 | QTest::newRow(dataTag: "Russian-Trad-1234M" ) << lang << 2 << traditionalFormat << 1234567890 << QString("1,15 \u0413\u0411" ); |
2942 | |
2943 | QTest::newRow(dataTag: "Russian-Decimal-0" ) << lang << 2 << siFormat << 0 << QString("0 \u0431\u0430\u0439\u0442\u044B" ); |
2944 | QTest::newRow(dataTag: "Russian-Decimal-10" ) << lang << 2 << siFormat << 10 << QString("10 \u0431\u0430\u0439\u0442\u044B" ); |
2945 | QTest::newRow(dataTag: "Russian-Decimal-16Ki" ) << lang << 2 << siFormat << 16384 << QString("16,38 \u043A\u0411" ); |
2946 | QTest::newRow(dataTag: "Russian-Decimal-1234k" ) << lang << 2 << siFormat << 1234567 << QString("1,23 \u041C\u0411" ); |
2947 | QTest::newRow(dataTag: "Russian-Decimal-1374k" ) << lang << 2 << siFormat << 1374744 << QString("1,37 \u041C\u0411" ); |
2948 | QTest::newRow(dataTag: "Russian-Decimal-1234M" ) << lang << 2 << siFormat << 1234567890 << QString("1,23 \u0413\u0411" ); |
2949 | } |
2950 | |
2951 | void tst_QLocale::formattedDataSize() |
2952 | { |
2953 | QFETCH(QLocale::Language, language); |
2954 | QFETCH(int, decimalPlaces); |
2955 | QFETCH(QLocale::DataSizeFormats, units); |
2956 | QFETCH(int, bytes); |
2957 | QFETCH(QString, output); |
2958 | QCOMPARE(QLocale(language).formattedDataSize(bytes, decimalPlaces, units), output); |
2959 | } |
2960 | |
2961 | void tst_QLocale::bcp47Name_data() |
2962 | { |
2963 | QTest::addColumn<QString>(name: "expect" ); |
2964 | |
2965 | QTest::newRow(dataTag: "C" ) << QStringLiteral("en" ); |
2966 | QTest::newRow(dataTag: "en" ) << QStringLiteral("en" ); |
2967 | QTest::newRow(dataTag: "en_US" ) << QStringLiteral("en" ); |
2968 | QTest::newRow(dataTag: "en_GB" ) << QStringLiteral("en-GB" ); |
2969 | QTest::newRow(dataTag: "en_DE" ) << QStringLiteral("en-DE" ); |
2970 | QTest::newRow(dataTag: "de_DE" ) << QStringLiteral("de" ); |
2971 | QTest::newRow(dataTag: "sr_RS" ) << QStringLiteral("sr" ); |
2972 | QTest::newRow(dataTag: "sr_Cyrl_RS" ) << QStringLiteral("sr" ); |
2973 | QTest::newRow(dataTag: "sr_Latn_RS" ) << QStringLiteral("sr-Latn" ); |
2974 | QTest::newRow(dataTag: "sr_ME" ) << QStringLiteral("sr-ME" ); |
2975 | QTest::newRow(dataTag: "sr_Cyrl_ME" ) << QStringLiteral("sr-Cyrl-ME" ); |
2976 | QTest::newRow(dataTag: "sr_Latn_ME" ) << QStringLiteral("sr-ME" ); |
2977 | |
2978 | // Fall back to defaults when country isn't in CLDR for this language: |
2979 | QTest::newRow(dataTag: "sr_HR" ) << QStringLiteral("sr" ); |
2980 | QTest::newRow(dataTag: "sr_Cyrl_HR" ) << QStringLiteral("sr" ); |
2981 | QTest::newRow(dataTag: "sr_Latn_HR" ) << QStringLiteral("sr-Latn" ); |
2982 | } |
2983 | |
2984 | void tst_QLocale::bcp47Name() |
2985 | { |
2986 | QFETCH(QString, expect); |
2987 | QCOMPARE(QLocale(QLatin1String(QTest::currentDataTag())).bcp47Name(), expect); |
2988 | } |
2989 | |
2990 | class MySystemLocale : public QSystemLocale |
2991 | { |
2992 | public: |
2993 | MySystemLocale(const QString &locale) : m_name(locale), m_locale(locale) |
2994 | { |
2995 | } |
2996 | |
2997 | QVariant query(QueryType type, QVariant /*in*/) const override |
2998 | { |
2999 | return type == UILanguages ? QVariant(QStringList{m_name}) : QVariant(); |
3000 | } |
3001 | |
3002 | QLocale fallbackUiLocale() const override |
3003 | { |
3004 | return m_locale; |
3005 | } |
3006 | |
3007 | private: |
3008 | const QString m_name; |
3009 | const QLocale m_locale; |
3010 | }; |
3011 | |
3012 | void tst_QLocale::systemLocale_data() |
3013 | { |
3014 | // Test uses MySystemLocale, so is platform-independent. |
3015 | QTest::addColumn<QString>(name: "name" ); |
3016 | QTest::addColumn<QLocale::Language>(name: "language" ); |
3017 | QTest::addColumn<QStringList>(name: "uiLanguages" ); |
3018 | |
3019 | QTest::addRow(format: "catalan" ) |
3020 | << QString("ca" ) << QLocale::Catalan |
3021 | << QStringList{QStringLiteral("ca" ), QStringLiteral("ca-ES" ), QStringLiteral("ca-Latn-ES" )}; |
3022 | QTest::addRow(format: "ukrainian" ) |
3023 | << QString("uk" ) << QLocale::Ukrainian |
3024 | << QStringList{QStringLiteral("uk" ), QStringLiteral("uk-UA" ), QStringLiteral("uk-Cyrl-UA" )}; |
3025 | QTest::addRow(format: "german" ) |
3026 | << QString("de" ) << QLocale::German |
3027 | << QStringList{QStringLiteral("de" ), QStringLiteral("de-DE" ), QStringLiteral("de-Latn-DE" )}; |
3028 | QTest::addRow(format: "chinese-min" ) |
3029 | << QString("zh" ) << QLocale::Chinese |
3030 | << QStringList{QStringLiteral("zh" ), QStringLiteral("zh-CN" ), QStringLiteral("zh-Hans-CN" )}; |
3031 | QTest::addRow(format: "chinese-full" ) |
3032 | << QString("zh-Hans-CN" ) << QLocale::Chinese |
3033 | << QStringList{QStringLiteral("zh-Hans-CN" ), QStringLiteral("zh" ), QStringLiteral("zh-CN" )}; |
3034 | } |
3035 | |
3036 | void tst_QLocale::systemLocale() |
3037 | { |
3038 | QLocale originalLocale; |
3039 | QLocale originalSystemLocale = QLocale::system(); |
3040 | |
3041 | QFETCH(QString, name); |
3042 | QFETCH(QLocale::Language, language); |
3043 | QFETCH(QStringList, uiLanguages); |
3044 | |
3045 | { |
3046 | MySystemLocale sLocale(name); |
3047 | QCOMPARE(QLocale().language(), language); |
3048 | QCOMPARE(QLocale::system().language(), language); |
3049 | QCOMPARE(QLocale::system().uiLanguages(), uiLanguages); |
3050 | } |
3051 | |
3052 | QCOMPARE(QLocale(), originalLocale); |
3053 | QCOMPARE(QLocale::system(), originalSystemLocale); |
3054 | } |
3055 | |
3056 | void tst_QLocale::IndianNumberGrouping() |
3057 | { |
3058 | QLocale indian(QLocale::Hindi, QLocale::India); |
3059 | |
3060 | qint8 int8 = 100; |
3061 | QString strResult8("100" ); |
3062 | QCOMPARE(indian.toString(int8), strResult8); |
3063 | QCOMPARE(indian.toShort(strResult8), short(int8)); |
3064 | |
3065 | quint8 uint8 = 100; |
3066 | QCOMPARE(indian.toString(uint8), strResult8); |
3067 | QCOMPARE(indian.toShort(strResult8), short(uint8)); |
3068 | |
3069 | // Boundary case 1000 for short and ushort |
3070 | short shortInt = 1000; |
3071 | QString strResult16("1,000" ); |
3072 | QCOMPARE(indian.toString(shortInt), strResult16); |
3073 | QCOMPARE(indian.toShort(strResult16), shortInt); |
3074 | |
3075 | ushort uShortInt = 1000; |
3076 | QCOMPARE(indian.toString(uShortInt), strResult16); |
3077 | QCOMPARE(indian.toUShort(strResult16), uShortInt); |
3078 | |
3079 | shortInt = 10000; |
3080 | strResult16 = "10,000" ; |
3081 | QCOMPARE(indian.toString(shortInt), strResult16); |
3082 | QCOMPARE(indian.toShort(strResult16), shortInt); |
3083 | |
3084 | uShortInt = 10000; |
3085 | QCOMPARE(indian.toString(uShortInt), strResult16); |
3086 | QCOMPARE(indian.toUShort(strResult16), uShortInt); |
3087 | |
3088 | int intInt = 1000000000; |
3089 | QString strResult32("1,00,00,00,000" ); |
3090 | QCOMPARE(indian.toString(intInt), strResult32); |
3091 | QCOMPARE(indian.toInt(strResult32), intInt); |
3092 | |
3093 | uint uIntInt = 1000000000; |
3094 | QCOMPARE(indian.toString(uIntInt), strResult32); |
3095 | QCOMPARE(indian.toUInt(strResult32), uIntInt); |
3096 | |
3097 | QString strResult64("10,00,00,00,00,00,00,00,000" ); |
3098 | qint64 int64 = Q_INT64_C(1000000000000000000); |
3099 | QCOMPARE(indian.toString(int64), strResult64); |
3100 | QCOMPARE(indian.toLongLong(strResult64), int64); |
3101 | |
3102 | quint64 uint64 = Q_UINT64_C(1000000000000000000); |
3103 | QCOMPARE(indian.toString(uint64), strResult64); |
3104 | QCOMPARE(indian.toULongLong(strResult64), uint64); |
3105 | } |
3106 | |
3107 | QTEST_MAIN(tst_QLocale) |
3108 | #include "tst_qlocale.moc" |
3109 | |