File indexing completed on 2024-05-12 16:36:00

0001 /* This file is part of the KDE project
0002    Copyright 2015 Marijn Kruisselbrink <mkruisselbrink@kde.org>
0003 
0004    This library is free software; you can redistribute it and/or
0005    modify it under the terms of the GNU Library General Public
0006    License as published by the Free Software Foundation; only
0007    version 2 of the License.
0008 
0009    This library is distributed in the hope that it will be useful,
0010    but WITHOUT ANY WARRANTY; without even the implied warranty of
0011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0012    Library General Public License for more details.
0013 
0014    You should have received a copy of the GNU Library General Public License
0015    along with this library; see the file COPYING.LIB.  If not, write to
0016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0017    Boston, MA 02110-1301, USA.
0018 */
0019 #include "TestValueConverter.h"
0020 
0021 #include <ValueConverter.h>
0022 
0023 #include <CalculationSettings.h>
0024 #include <ValueParser.h>
0025 #include <ValueStorage.h>
0026 
0027 #include <klocale.h>
0028 
0029 #include <QTest>
0030 
0031 #include <locale.h>
0032 
0033 Q_DECLARE_METATYPE(complex<Number>)
0034 
0035 using namespace Calligra::Sheets;
0036 
0037 namespace {
0038 
0039 template<typename T>
0040 Value ValueWithFormat(T i, Value::Format fmt)
0041 {
0042     Value result(i);
0043     result.setFormat(fmt);
0044     return result;
0045 }
0046 
0047 } // namespace
0048 
0049 void TestValueConverter::initTestCase()
0050 {
0051     m_calcsettings = new CalculationSettings();
0052     m_parser = new ValueParser(m_calcsettings);
0053     m_converter = new ValueConverter(m_parser);
0054 
0055     // Custom reference date to make sure all date conversions use this date.
0056     m_calcsettings->setReferenceDate(QDate(2000, 1, 1));
0057 
0058     QStandardPaths::setTestModeEnabled(true);
0059 
0060     // If run with 'C' locale translations will fail
0061     // Setting it to 'C.UTF-8' fixes this
0062     char *l = setlocale(LC_MESSAGES, 0);
0063     if (l && strcmp(l, "C") == 0) {
0064         setlocale(LC_MESSAGES, "C.UTF-8");
0065         qDebug()<<"Set locale:"<<l<<"->"<<setlocale(LC_MESSAGES, 0);
0066     }
0067 
0068     // Some tests need translations of certain words.
0069     // These are available in .mo file in the data directory.
0070     // Install these xx translations into test path for some arbitrary language.
0071     // We use the 'nl'.
0072     QString locale = "nl";
0073     QString dataPath = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
0074     QString localePath = dataPath + "/locale/" + locale + "/LC_MESSAGES";
0075     QVERIFY(QDir(localePath).mkpath("."));
0076     m_translationsFile = localePath + "/calligrasheets.mo";
0077     if (QFile::exists(m_translationsFile)) {
0078         QFile::remove(m_translationsFile);
0079     }
0080     // NOTE: sheets.mo -> calligrasheets.mo. Maybe rename sheets.mo
0081     QVERIFY(QFile::copy(QFINDTESTDATA("data/sheets.mo"), m_translationsFile));
0082 
0083     // check that translation ok, else lot of tests will fail later
0084     *m_calcsettings->locale() = KLocale(locale, locale);
0085     QCOMPARE(m_calcsettings->locale()->country(), locale);
0086     QString s = ki18n("true").toString(QStringList()<<locale);
0087     QVERIFY2(s == QString("xxtruexx"), "Translation failed, check that you have the correct .mo file in the data directory and that it installs correctly");
0088 }
0089 
0090 void TestValueConverter::cleanupTestCase()
0091 {
0092     QStandardPaths::setTestModeEnabled(false);
0093     QFile::remove(m_translationsFile);
0094 
0095     delete m_converter;
0096     delete m_parser;
0097     delete m_calcsettings;
0098 }
0099 
0100 void TestValueConverter::testAsBoolean_data()
0101 {
0102     QTest::addColumn<QString>("locale");
0103     QTest::addColumn<Value>("value");
0104     QTest::addColumn<bool>("expectedOk");
0105     QTest::addColumn<bool>("expected");
0106 
0107     QTest::newRow("empty") << "C" << Value() << true << false;
0108 
0109     QTest::newRow("bool true") << "C" << Value(true) << true << true;
0110     QTest::newRow("bool false") << "C" << Value(false) << true << false;
0111 
0112     QTest::newRow("integer <0") << "C" << Value(-5) << true << true;
0113     QTest::newRow("integer =0") << "C" << Value(0) << true << false;
0114     QTest::newRow("integer >0") << "C" << Value(1) << true << true;
0115 
0116     QTest::newRow("float <0") << "C" << Value(-0.00001) << true << true;
0117     QTest::newRow("float =0") << "C" << Value(0.0) << true << false;
0118     QTest::newRow("float >0") << "C" << Value(1e-99) << true << true;
0119 
0120     QTest::newRow("complex -1 0i") << "C" << Value(complex<Number>(-1, 0)) << true << true;
0121     QTest::newRow("complex  0 0i") << "C" << Value(complex<Number>(0, 0)) << true << false;
0122     QTest::newRow("complex +1 0i") << "C" << Value(complex<Number>(1, 0)) << true << true;
0123     QTest::newRow("complex -1 1i") << "C" << Value(complex<Number>(-1, 1)) << true << true;
0124     QTest::newRow("complex  0 1i") << "C" << Value(complex<Number>(0, 1)) << true << false;
0125     QTest::newRow("complex +1 1i") << "C" << Value(complex<Number>(1, 1)) << true << true;
0126 
0127     QTest::newRow("string en true") << "C" << Value("true") << true << true;
0128     QTest::newRow("string en false") << "C" << Value("false") << true << false;
0129     QTest::newRow("string en foobar") << "C" << Value("foobar") << false << false;
0130     QTest::newRow("string en TruE") << "C" << Value("TruE") << true << true;
0131     QTest::newRow("string en fAlSe") << "C" << Value("fAlSe") << true << false;
0132     QTest::newRow("string en xxtruexx") << "C" << Value("xxtruexx") << false << false;
0133     QTest::newRow("string xx true") << "nl" << Value("true") << true << true;
0134     QTest::newRow("string xx false") << "nl" << Value("false") << true << false;
0135     QTest::newRow("string xx foobar") << "nl" << Value("foobar") << false << false;
0136     QTest::newRow("string xx TruE") << "nl" << Value("TruE") << true << true;
0137     QTest::newRow("string xx fAlSe") << "nl" << Value("fAlSe") << true << false;
0138     QTest::newRow("string xx xxtruexx") << "nl" << Value("xxtruexx") << true << true;
0139     QTest::newRow("string xx xxtRuexx") << "nl" << Value("xxtRuexx") << true << true;
0140     QTest::newRow("string xx xxfalSexx") << "nl" << Value("xxfalSexx") << true << false;
0141 
0142     ValueStorage array;
0143     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true << false;
0144     array.insert(1, 1, Value(true));
0145     QTest::newRow("array true") << "C" << Value(array, QSize(1, 1)) << true << true;
0146 
0147     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << false;
0148     QTest::newRow("errorNA") << "C" << Value::errorNA() << true << false;
0149 }
0150 
0151 void TestValueConverter::testAsBoolean()
0152 {
0153     QFETCH(QString, locale);
0154     QFETCH(Value, value);
0155     QFETCH(bool, expectedOk);
0156     QFETCH(bool, expected);
0157 
0158     *m_calcsettings->locale() = KLocale(locale, locale);
0159     QCOMPARE(m_calcsettings->locale()->country(), locale);
0160 
0161     bool ok;
0162     Value result = m_converter->asBoolean(value, &ok);
0163     QCOMPARE(ok, expectedOk);
0164     QCOMPARE(result, Value(expected));
0165     QCOMPARE(m_converter->toBoolean(value), expected);
0166 }
0167 
0168 void TestValueConverter::testAsInteger_data()
0169 {
0170     QTest::addColumn<QString>("locale");
0171     QTest::addColumn<Value>("value");
0172     QTest::addColumn<bool>("expectedOk");
0173     QTest::addColumn<int>("expected");
0174 
0175     QTest::newRow("empty") << "C" << Value() << true << 0;
0176 
0177     QTest::newRow("bool true") << "C" << Value(true) << true << 1;
0178     QTest::newRow("bool false") << "C" << Value(false) << true << 0;
0179 
0180     QTest::newRow("integer") << "C" << Value(94610) << true << 94610;
0181 
0182     QTest::newRow("float 0") << "C" << Value(0.0) << true << 0;
0183     QTest::newRow("float 3.3") << "C" << Value(3.3) << true << 3;
0184     QTest::newRow("float 123.9999") << "C" << Value(123.9999) << true << 123;
0185     QTest::newRow("float -45.65") << "C" << Value(-45.65) << true << -46;
0186 
0187     QTest::newRow("complex 0 0i") << "C" << Value(complex<Number>(0, 0)) << true << 0;
0188     QTest::newRow("complex 1.6 -3i") << "C" << Value(complex<Number>(1.6, -3)) << true << 1;
0189     QTest::newRow("complex 2 4.6i") << "C" << Value(complex<Number>(2, 4.6)) << true << 2;
0190     QTest::newRow("complex -3.14 1i") << "C" << Value(complex<Number>(-3.14, 1)) << true << -4;
0191 
0192     QTest::newRow("string 123") << "C" << Value("123") << true << 123;
0193     QTest::newRow("string -456") << "C" << Value("-456") << true << -456;
0194     QTest::newRow("string +5") << "C" << Value("+5") << true << 5;
0195     QTest::newRow("string 1501%") << "C" << Value("1501%") << true << 15;
0196     QTest::newRow("string 5+3i") << "C" << Value("5+3i") << true << 5;
0197     QTest::newRow("string 2.4 + 3j") << "C" << Value("2.4 + 3j") << true << 2;
0198     QTest::newRow("string 6 - 3i") << "C" << Value("6 - 3i") << true << 6;
0199     QTest::newRow("string 2.4i") << "C" << Value("2.4i") << true << 0;
0200     QTest::newRow("string 1,4") << "C" << Value("1,4") << false << 0;
0201     QTest::newRow("string 1,400") << "C" << Value("1,400") << true << 1400;
0202     QTest::newRow("string 3 5/2") << "C" << Value("3 5/2") << true << 5;
0203     QTest::newRow("string 3e2") << "C" << Value("3e2") << true << 300;
0204     QTest::newRow("string 1234E-2") << "C" << Value("1234E-2") << true << 12;
0205     QTest::newRow("string nl 1,4") << "nl" << Value("1,4") << true << 1;
0206     QTest::newRow("string nl 1,400") << "nl" << Value("1,400") << true << 1;
0207 
0208     ValueStorage array;
0209     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true << 0;
0210     array.insert(1, 1, Value(543));
0211     QTest::newRow("array 543") << "C" << Value(array, QSize(1, 1)) << true << 543;
0212 
0213     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << 0;
0214     QTest::newRow("errorNA") << "C" << Value::errorNA() << true << 0;
0215 }
0216 
0217 void TestValueConverter::testAsInteger()
0218 {
0219     QFETCH(QString, locale);
0220     QFETCH(Value, value);
0221     QFETCH(bool, expectedOk);
0222     QFETCH(int, expected);
0223 
0224     *m_calcsettings->locale() = KLocale(locale, locale);
0225     QCOMPARE(m_calcsettings->locale()->country(), locale);
0226 
0227     bool ok;
0228     Value result = m_converter->asInteger(value, &ok);
0229     QCOMPARE(ok, expectedOk);
0230     QCOMPARE(result, Value(expected));
0231     QCOMPARE(m_converter->toInteger(value), expected);
0232 }
0233 
0234 void TestValueConverter::testAsFloat_data()
0235 {
0236     QTest::addColumn<QString>("locale");
0237     QTest::addColumn<Value>("value");
0238     QTest::addColumn<bool>("expectedOk");
0239     QTest::addColumn<double>("expected");
0240 
0241     QTest::newRow("empty") << "C" << Value() << true << 0.0;
0242 
0243     QTest::newRow("bool true") << "C" << Value(true) << true << 1.0;
0244     QTest::newRow("bool false") << "C" << Value(false) << true << 0.0;
0245 
0246     QTest::newRow("integer") << "C" << Value(94610) << true << 94610.0;
0247 
0248     QTest::newRow("float 0") << "C" << Value(0.0) << true << 0.0;
0249     QTest::newRow("float 3.3") << "C" << Value(3.3) << true << 3.3;
0250     QTest::newRow("float 123.9999") << "C" << Value(123.9999) << true << 123.9999;
0251     QTest::newRow("float -45.65") << "C" << Value(-45.65) << true << -45.65;
0252 
0253     QTest::newRow("complex 0 0i") << "C" << Value(complex<Number>(0, 0)) << true << 0.0;
0254     QTest::newRow("complex 1.6 -3i") << "C" << Value(complex<Number>(1.6, -3)) << true << 1.6;
0255     QTest::newRow("complex 2 4.6i") << "C" << Value(complex<Number>(2, 4.6)) << true << 2.0;
0256     QTest::newRow("complex -3.14 1i") << "C" << Value(complex<Number>(-3.14, 1)) << true << -3.14;
0257 
0258     QTest::newRow("string 123") << "C" << Value("123") << true << 123.0;
0259     QTest::newRow("string -456") << "C" << Value("-456") << true << -456.0;
0260     QTest::newRow("string +5") << "C" << Value("+5") << true << 5.0;
0261     QTest::newRow("string 1525%") << "C" << Value("1525%") << true << 15.25;
0262     QTest::newRow("string 5+3i") << "C" << Value("5+3i") << true << 5.0;
0263     QTest::newRow("string 2.4 + 3j") << "C" << Value("2.4 + 3j") << true << 2.4;
0264     QTest::newRow("string 6 - 3i") << "C" << Value("6 - 3i") << true << 6.0;
0265     QTest::newRow("string 2.4i") << "C" << Value("2.4i") << true << 0.0;
0266     QTest::newRow("string 1,4") << "C" << Value("1,4") << false << 0.0;
0267     QTest::newRow("string 1,400") << "C" << Value("1,400") << true << 1400.0;
0268     QTest::newRow("string 3 5/2") << "C" << Value("3 5/2") << true << 5.5;
0269     QTest::newRow("string 3e2") << "C" << Value("3e2") << true << 300.0;
0270     QTest::newRow("string 1234E-2") << "C" << Value("1234E-2") << true << 12.34;
0271     QTest::newRow("string nl 1,4") << "nl" << Value("1,4") << true << 1.4;
0272     QTest::newRow("string nl 1,400") << "nl" << Value("1,400") << true << 1.4;
0273 
0274     ValueStorage array;
0275     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true << 0.0;
0276     array.insert(1, 1, Value(543.4));
0277     QTest::newRow("array 543.4") << "C" << Value(array, QSize(1, 1)) << true << 543.4;
0278 
0279     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << 0.0;
0280     QTest::newRow("errorNA") << "C" << Value::errorNA() << true << 0.0;
0281 }
0282 
0283 void TestValueConverter::testAsFloat()
0284 {
0285     QFETCH(QString, locale);
0286     QFETCH(Value, value);
0287     QFETCH(bool, expectedOk);
0288     QFETCH(double, expected);
0289 
0290     *m_calcsettings->locale() = KLocale(locale, locale);
0291     QCOMPARE(m_calcsettings->locale()->country(), locale);
0292 
0293     bool ok;
0294     Value result = m_converter->asFloat(value, &ok);
0295     QCOMPARE(ok, expectedOk);
0296     QCOMPARE(result, Value(expected));
0297     QCOMPARE(m_converter->toFloat(value), Number(expected));
0298 }
0299 
0300 void TestValueConverter::testAsComplex_data()
0301 {
0302     QTest::addColumn<QString>("locale");
0303     QTest::addColumn<Value>("value");
0304     QTest::addColumn<bool>("expectedOk");
0305     QTest::addColumn<complex<Number>>("expected");
0306 
0307     QTest::newRow("empty") << "C" << Value() << true << complex<Number>(0, 0);
0308 
0309     QTest::newRow("bool true") << "C" << Value(true) << true << complex<Number>(1, 0);
0310     QTest::newRow("bool false") << "C" << Value(false) << true << complex<Number>(0, 0);
0311 
0312     QTest::newRow("integer") << "C" << Value(94610) << true << complex<Number>(94610, 0);
0313 
0314     QTest::newRow("float 0") << "C" << Value(0.0) << true << complex<Number>(0, 0);
0315     QTest::newRow("float 3.3") << "C" << Value(3.3) << true << complex<Number>(3.3, 0);
0316     QTest::newRow("float 123.9999") << "C" << Value(123.9999)
0317         << true << complex<Number>(123.9999, 0);
0318     QTest::newRow("float -45.65") << "C" << Value(-45.65)
0319         << true << complex<Number>(-45.65, 0);
0320 
0321     QTest::newRow("complex 0 0i") << "C" << Value(complex<Number>(0, 0))
0322         << true << complex<Number>(0, 0);
0323     QTest::newRow("complex 1.6 -3i") << "C" << Value(complex<Number>(1.6, -3))
0324         << true << complex<Number>(1.6, -3);
0325     QTest::newRow("complex 2 4.6i") << "C" << Value(complex<Number>(2, 4.6))
0326         << true << complex<Number>(2, 4.6);
0327     QTest::newRow("complex -3.14 1i") << "C" << Value(complex<Number>(-3.14, 1))
0328         << true << complex<Number>(-3.14, 1);
0329 
0330     QTest::newRow("string 123") << "C" << Value("123")
0331         << true << complex<Number>(123, 0);
0332     QTest::newRow("string -456") << "C" << Value("-456")
0333         << true << complex<Number>(-456, 0);
0334     QTest::newRow("string +5") << "C" << Value("+5")
0335         << true << complex<Number>(5, 0);
0336     QTest::newRow("string 1525%") << "C" << Value("1525%")
0337         << true << complex<Number>(15.25, 0);
0338     QTest::newRow("string 5+3i") << "C" << Value("5+3i")
0339         << true << complex<Number>(5, 3);
0340     QTest::newRow("string 2.4 + 3j") << "C" << Value("2.4 + 3j")
0341         << true << complex<Number>(2.4, 3);
0342     QTest::newRow("string 6 - 3i") << "C" << Value("6 - 3i")
0343         << true << complex<Number>(6, -3);
0344     QTest::newRow("string 2.4i") << "C" << Value("2.4i")
0345         << true << complex<Number>(0, 2.4);
0346     QTest::newRow("string 1,4") << "C" << Value("1,4")
0347         << false << complex<Number>(0, 0);
0348     QTest::newRow("string 1,400") << "C" << Value("1,400")
0349         << true << complex<Number>(1400, 0);
0350     QTest::newRow("string 3 5/2") << "C" << Value("3 5/2")
0351         << true << complex<Number>(5.5, 0);
0352     QTest::newRow("string 3e2") << "C" << Value("3e2")
0353         << true << complex<Number>(300.0, 0);
0354     QTest::newRow("string 1234E-2") << "C" << Value("1234E-2")
0355         << true << complex<Number>(12.34, 0);
0356     QTest::newRow("string 12.34e5 + 4.2e2i") << "C" << Value("12.34e5 + 4.2e2i")
0357         << true << complex<Number>(12.34e5, 4.2e2);
0358     QTest::newRow("string 12.34e5 + 4.2e+2i") << "C" << Value("12.34e5 + 4.2e+2i")
0359         << true << complex<Number>(12.34e5, 4.2e2);
0360     //QTest::newRow("string 12.34e+5 + 4.2e2i") << "C" << Value("12.34e+5 + 4.2e2i")
0361     //    << true << complex<Number>(12.34e5, 4.2e2);
0362     //QTest::newRow("string 12.34e+5 + 4.2e+2i") << "C" << Value("12.34e+5 + 4.2e+2i")
0363     //    << true << complex<Number>(12.34e5, 4.2e2);
0364     QTest::newRow("string nl 1,4") << "nl" << Value("1,4")
0365         << true << complex<Number>(1.4, 0);
0366     QTest::newRow("string nl 1,400") << "nl" << Value("1,400")
0367         << true << complex<Number>(1.4, 0);
0368 
0369     ValueStorage array;
0370     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1))
0371         << true << complex<Number>(0, 0);
0372     array.insert(1, 1, Value(543.4));
0373     QTest::newRow("array 543.4") << "C" << Value(array, QSize(1, 1))
0374         << true << complex<Number>(543.4, 0);
0375 
0376     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE()
0377         << true << complex<Number>(0, 0);
0378     QTest::newRow("errorNA") << "C" << Value::errorNA()
0379         << true << complex<Number>(0, 0);
0380 }
0381 
0382 void TestValueConverter::testAsComplex()
0383 {
0384     QFETCH(QString, locale);
0385     QFETCH(Value, value);
0386     QFETCH(bool, expectedOk);
0387     QFETCH(complex<Number>, expected);
0388 
0389     *m_calcsettings->locale() = KLocale(locale, locale);
0390     QCOMPARE(m_calcsettings->locale()->country(), locale);
0391 
0392     bool ok;
0393     Value result = m_converter->asComplex(value, &ok);
0394     QCOMPARE(ok, expectedOk);
0395     QCOMPARE(result, Value(expected));
0396     QCOMPARE(m_converter->toComplex(value), expected);
0397 }
0398 
0399 void TestValueConverter::testAsNumeric_data()
0400 {
0401     QTest::addColumn<QString>("locale");
0402     QTest::addColumn<Value>("value");
0403     QTest::addColumn<bool>("expectedOk");
0404     QTest::addColumn<Value>("expected");
0405 
0406     QTest::newRow("empty") << "C" << Value() << true << Value(0.0);
0407 
0408     QTest::newRow("bool true") << "C" << Value(true) << true << Value(1.0);
0409     QTest::newRow("bool false") << "C" << Value(false) << true << Value(0.0);
0410 
0411     QTest::newRow("integer") << "C" << Value(94610) << true << Value(94610);
0412 
0413     QTest::newRow("float 0") << "C" << Value(0.0) << true << Value(0.0);
0414     QTest::newRow("float 3.3") << "C" << Value(3.3) << true << Value(3.3);
0415     QTest::newRow("float 123.9999") << "C" << Value(123.9999) << true << Value(123.9999);
0416     QTest::newRow("float -45.65") << "C" << Value(-45.65) << true << Value(-45.65);
0417 
0418     QTest::newRow("complex 0 0i") << "C" << Value(complex<Number>(0, 0))
0419         << true << Value(complex<Number>(0, 0));
0420     QTest::newRow("complex 1.6 -3i") << "C" << Value(complex<Number>(1.6, -3))
0421         << true << Value(complex<Number>(1.6, -3));
0422     QTest::newRow("complex 2 4.6i") << "C" << Value(complex<Number>(2, 4.6))
0423         << true << Value(complex<Number>(2, 4.6));
0424     QTest::newRow("complex -3.14 1i") << "C" << Value(complex<Number>(-3.14, 1))
0425         << true << Value(complex<Number>(-3.14, 1));
0426 
0427     QTest::newRow("string 123") << "C" << Value("123") << true << Value(123);
0428     QTest::newRow("string -456") << "C" << Value("-456") << true << Value(-456);
0429     QTest::newRow("string +5") << "C" << Value("+5") << true << Value(5);
0430     QTest::newRow("string 1525%") << "C" << Value("1525%") << true << Value(15.25);
0431     QTest::newRow("string 5+3i") << "C" << Value("5+3i") << true << Value(complex<Number>(5, 3));
0432     QTest::newRow("string 2.4 + 3j") << "C" << Value("2.4 + 3j")
0433         << true << Value(complex<Number>(2.4, 3));
0434     QTest::newRow("string 6 - 3i") << "C" << Value("6 - 3i")
0435         << true << Value(complex<Number>(6, -3));
0436     QTest::newRow("string 2.4i") << "C" << Value("2.4i") << true << Value(complex<Number>(0, 2.4));
0437     QTest::newRow("string 1,4") << "C" << Value("1,4") << false << Value(0.0);
0438     QTest::newRow("string 1,400") << "C" << Value("1,400") << true << Value(1400);
0439     QTest::newRow("string 3 5/2") << "C" << Value("3 5/2") << true << Value(5.5);
0440     QTest::newRow("string 3e2") << "C" << Value("3e2") << true << Value(300.0);
0441     QTest::newRow("string 1234E-2") << "C" << Value("1234E-2") << true << Value(12.34);
0442     QTest::newRow("string nl 1,4") << "nl" << Value("1,4") << true << Value(1.4);
0443     QTest::newRow("string nl 1,400") << "nl" << Value("1,400") << true << Value(1.4);
0444 
0445     ValueStorage array;
0446     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true << Value(0.0);
0447     array.insert(1, 1, Value(543.4));
0448     QTest::newRow("array 543.4") << "C" << Value(array, QSize(1, 1)) << true << Value(543.4);
0449 
0450     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << Value(0.0);
0451     QTest::newRow("errorNA") << "C" << Value::errorNA() << true << Value(0.0);
0452 }
0453 
0454 void TestValueConverter::testAsNumeric()
0455 {
0456     QFETCH(QString, locale);
0457     QFETCH(Value, value);
0458     QFETCH(bool, expectedOk);
0459     QFETCH(Value, expected);
0460 
0461     *m_calcsettings->locale() = KLocale(locale, locale);
0462     QCOMPARE(m_calcsettings->locale()->country(), locale);
0463 
0464     bool ok;
0465     Value result = m_converter->asNumeric(value, &ok);
0466     QCOMPARE(ok, expectedOk);
0467     QCOMPARE(result, expected);
0468 }
0469 
0470 void TestValueConverter::testAsString_data()
0471 {
0472     QTest::addColumn<QString>("locale");
0473     QTest::addColumn<Value>("value");
0474     QTest::addColumn<QString>("expected");
0475 
0476     QTest::newRow("empty") << "C" << Value() << "";
0477 
0478     QTest::newRow("bool True") << "C" << Value(true) << "True";
0479     QTest::newRow("bool False") << "C" << Value(false) << "False";
0480     QTest::newRow("bool True xx") << "nl" << Value(true) << "xxTruexx";
0481     QTest::newRow("bool False xx") << "nl" << Value(false) << "xxFalsexx";
0482 
0483     QTest::newRow("integer plain") << "C" << Value(123) << "123";
0484     QTest::newRow("integer percent") << "C" << ValueWithFormat(3, Value::fmt_Percent)
0485         << "300 %";
0486     QTest::newRow("integer time") << "C" << ValueWithFormat(4, Value::fmt_Time) << "00:00";
0487     QTest::newRow("integer time us") << "us" << ValueWithFormat(4, Value::fmt_Time)
0488         << "12:00 AM";
0489     // TODO(mek): These next ones should almost certainly be using short date format.
0490     QTest::newRow("integer date 1") << "C" << ValueWithFormat(0, Value::fmt_Date)
0491         << "Saturday 01 January 2000";
0492     QTest::newRow("integer date 2") << "C" << ValueWithFormat(2000, Value::fmt_Date)
0493         << "Thursday 23 June 2005";
0494     QTest::newRow("integer date 3") << "C" << ValueWithFormat(-10, Value::fmt_Date)
0495         << "Wednesday 22 December 1999";
0496     // TODO(mek): KLocale doesn't take its language into account when formatting dates...
0497     //QTest::newRow("integer date 1 nl") << "nl" << ValueWithFormat(0, Value::fmt_Date)
0498     //    << "xxSaturdayxx 01 xxJanuaryxx 2000";
0499     //QTest::newRow("integer date 2 nl") << "nl" << ValueWithFormat(2000, Value::fmt_Date)
0500     //    << "xxThursdayxx 23 xxJunexx 2005";
0501     //QTest::newRow("integer date 3 nl") << "nl" << ValueWithFormat(-10, Value::fmt_Date)
0502     //    << "xxWednesdayxx 22 xxDecemberxx 1999";
0503     QTest::newRow("integer datetime 1") << "C" << ValueWithFormat(4, Value::fmt_DateTime)
0504         << "2000-01-05 00:00";
0505     QTest::newRow("integer datetime 1 us") << "us" << ValueWithFormat(4, Value::fmt_DateTime)
0506         << "01/05/00 12:00 AM";
0507     QTest::newRow("integer datetime 1 nl") << "nl" << ValueWithFormat(4, Value::fmt_DateTime)
0508         << "05/01/00 00:00";
0509     QTest::newRow("integer datetime 2") << "C" << ValueWithFormat(-10, Value::fmt_DateTime)
0510         << "1999-12-22 00:00";
0511     QTest::newRow("integer datetime 2 us") << "us" << ValueWithFormat(-10, Value::fmt_DateTime)
0512         << "12/22/99 12:00 AM";
0513     QTest::newRow("integer datetime 2 nl") << "nl" << ValueWithFormat(-10, Value::fmt_DateTime)
0514         << "22/12/99 00:00";
0515 
0516     QTest::newRow("float 123") << "C" << Value(123.0) << "123";
0517     QTest::newRow("float -3.14") << "C" << Value(-3.14) << "-3.14";
0518     QTest::newRow("float 1.5e99") << "C" << Value(1.5e99) << "1.5e+99";
0519     QTest::newRow("float 0.43e-12") << "C" << Value(0.43e-12) << "4.3e-13";
0520     QTest::newRow("float 123 nl") << "nl" << Value(123.0) << "123";
0521     QTest::newRow("float -3.14 nl") << "nl" << Value(-3.14) << "-3,14";
0522     QTest::newRow("float 1.5e99 nl") << "nl" << Value(1.5e99) << "1,5e+99";
0523     QTest::newRow("float 0.43e-12 nl") << "nl" << Value(0.43e-12) << "4,3e-13";
0524     // TODO(mek): Currently buggy/inconsistent in implementation.
0525     //QTest::newRow("float percent") << "C" << ValueWithFormat(3.45, Value::fmt_Percent)
0526     //    << "345 %";
0527     QTest::newRow("float time 0") << "C" << ValueWithFormat(4, Value::fmt_Time) << "00:00";
0528     QTest::newRow("float time 1") << "C" << ValueWithFormat(0.5, Value::fmt_Time) << "12:00";
0529     QTest::newRow("float time 2") << "C" << ValueWithFormat(3.675, Value::fmt_Time) << "16:12";
0530     QTest::newRow("float time 0 us") << "us" << ValueWithFormat(4.0, Value::fmt_Time) << "12:00 AM";
0531     QTest::newRow("float time 1 us") << "us" << ValueWithFormat(0.5, Value::fmt_Time) << "12:00 PM";
0532     QTest::newRow("float time 2 us") << "us" << ValueWithFormat(3.675, Value::fmt_Time)
0533         << "04:12 PM";
0534     QTest::newRow("float date 1") << "C" << ValueWithFormat(0.5, Value::fmt_Date) << "2000-01-01";
0535     QTest::newRow("float date 2") << "C" << ValueWithFormat(2000.324, Value::fmt_Date)
0536         << "2005-06-23";
0537     QTest::newRow("float date 3") << "C" << ValueWithFormat(-9.234, Value::fmt_Date)
0538         << "1999-12-22";
0539     QTest::newRow("float date 1 nl") << "nl" << ValueWithFormat(0.5, Value::fmt_Date)
0540         << "01/01/00";
0541     QTest::newRow("float date 2 nl") << "nl" << ValueWithFormat(2000.324, Value::fmt_Date)
0542         << "23/06/05";
0543     QTest::newRow("float date 3 us") << "us" << ValueWithFormat(-9.234, Value::fmt_Date)
0544         << "12/22/99";
0545     QTest::newRow("float datetime 0") << "C" << ValueWithFormat(4.0, Value::fmt_DateTime)
0546         << "2000-01-05 00:00";
0547     QTest::newRow("float datetime 1") << "C" << ValueWithFormat(2000.5, Value::fmt_DateTime)
0548         << "2005-06-23 12:00";
0549     QTest::newRow("float datetime 2") << "C" << ValueWithFormat(-9.325, Value::fmt_DateTime)
0550         << "1999-12-22 16:12";
0551     QTest::newRow("float datetime 0 us") << "us" << ValueWithFormat(4.0, Value::fmt_DateTime)
0552         << "01/05/00 12:00 AM";
0553     QTest::newRow("float datetime 1 us") << "us" << ValueWithFormat(2000.5, Value::fmt_DateTime)
0554         << "06/23/05 12:00 PM";
0555     QTest::newRow("float datetime 2 us") << "us" << ValueWithFormat(-9.325, Value::fmt_DateTime)
0556         << "12/22/99 04:12 PM";
0557     QTest::newRow("float datetime 0 nl") << "nl" << ValueWithFormat(4.0, Value::fmt_DateTime)
0558         << "05/01/00 00:00";
0559     QTest::newRow("float datetime 1 nl") << "nl" << ValueWithFormat(2000.5, Value::fmt_DateTime)
0560         << "23/06/05 12:00";
0561     QTest::newRow("float datetime 2 nl") << "nl" << ValueWithFormat(-9.325, Value::fmt_DateTime)
0562         << "22/12/99 16:12";
0563 
0564     QTest::newRow("complex 0+0i") << "C" << Value(complex<Number>(0, 0)) << "0+0i";
0565     QTest::newRow("complex 3.14-2.7i") << "C" << Value(complex<Number>(3.14, -2.7)) << "3.14-2.7i";
0566     QTest::newRow("complex 2.2e99+3.3e88i") << "C" << Value(complex<Number>(2.2e99, 3.3e88))
0567         << "2.2e+99+3.3e+88i";
0568     QTest::newRow("complex time 0") << "C"
0569         << ValueWithFormat(complex<Number>(4, 3), Value::fmt_Time)
0570         << "00:00";
0571     QTest::newRow("complex time 1") << "C"
0572         << ValueWithFormat(complex<Number>(0.5, -3), Value::fmt_Time)
0573         << "12:00";
0574     QTest::newRow("complex time 2") << "C"
0575         << ValueWithFormat(complex<Number>(3.675, 653), Value::fmt_Time)
0576         << "16:12";
0577     QTest::newRow("complex time 0 us") << "us"
0578         << ValueWithFormat(complex<Number>(4, 634), Value::fmt_Time)
0579         << "12:00 AM";
0580     QTest::newRow("complex time 1 us") << "us"
0581         << ValueWithFormat(complex<Number>(0.5, 2.3), Value::fmt_Time)
0582         << "12:00 PM";
0583     QTest::newRow("complex time 2 us") << "us"
0584         << ValueWithFormat(complex<Number>(3.675, 2), Value::fmt_Time)
0585         << "04:12 PM";
0586     QTest::newRow("complex date 1") << "C"
0587         << ValueWithFormat(complex<Number>(0.5, 0), Value::fmt_Date)
0588         << "2000-01-01";
0589     QTest::newRow("complex date 2") << "C"
0590         << ValueWithFormat(complex<Number>(2000.324, 0), Value::fmt_Date)
0591         << "2005-06-23";
0592     QTest::newRow("complex date 3") << "C"
0593         << ValueWithFormat(complex<Number>(-9.234, 0), Value::fmt_Date)
0594         << "1999-12-22";
0595     QTest::newRow("complex date 1 nl") << "nl"
0596         << ValueWithFormat(complex<Number>(0.5, 0), Value::fmt_Date)
0597         << "01/01/00";
0598     QTest::newRow("complex date 2 nl") << "nl"
0599         << ValueWithFormat(complex<Number>(2000.324, 0), Value::fmt_Date)
0600         << "23/06/05";
0601     QTest::newRow("complex date 3 us") << "us"
0602         << ValueWithFormat(complex<Number>(-9.234, 0), Value::fmt_Date)
0603         << "12/22/99";
0604     QTest::newRow("complex datetime 0") << "C"
0605         << ValueWithFormat(complex<Number>(4.0, 0), Value::fmt_DateTime)
0606         << "2000-01-05 00:00";
0607     QTest::newRow("complex datetime 1") << "C"
0608         << ValueWithFormat(complex<Number>(2000.5, 0), Value::fmt_DateTime)
0609         << "2005-06-23 12:00";
0610     QTest::newRow("complex datetime 2") << "C"
0611         << ValueWithFormat(complex<Number>(-9.325, 0), Value::fmt_DateTime)
0612         << "1999-12-22 16:12";
0613     QTest::newRow("complex datetime 0 us") << "us"
0614         << ValueWithFormat(complex<Number>(4.0, 0), Value::fmt_DateTime)
0615         << "01/05/00 12:00 AM";
0616     QTest::newRow("complex datetime 1 us") << "us"
0617         << ValueWithFormat(complex<Number>(2000.5, 0), Value::fmt_DateTime)
0618         << "06/23/05 12:00 PM";
0619     QTest::newRow("complex datetime 2 us") << "us"
0620         << ValueWithFormat(complex<Number>(-9.325, 0), Value::fmt_DateTime)
0621         << "12/22/99 04:12 PM";
0622 
0623     QTest::newRow("string") << "C" << Value("foobar") << "foobar";
0624 
0625     ValueStorage array;
0626     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << "";
0627     array.insert(1, 1, Value(123));
0628     QTest::newRow("array 123") << "C" << Value(array, QSize(1, 1)) << "123";
0629 
0630     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << "#CIRCLE!";
0631     QTest::newRow("errorDEPEND") << "C" << Value::errorDEPEND() << "#DEPEND!";
0632     QTest::newRow("errorDIV0") << "C" << Value::errorDIV0() << "#DIV/0!";
0633     QTest::newRow("errorNA") << "C" << Value::errorNA() << "#N/A";
0634     QTest::newRow("errorNAME") << "C" << Value::errorNAME() << "#NAME?";
0635     QTest::newRow("errorNUM") << "C" << Value::errorNUM() << "#NUM!";
0636     QTest::newRow("errorNULL") << "C" << Value::errorNULL() << "#NULL!";
0637     QTest::newRow("errorPARSE") << "C" << Value::errorPARSE() << "#PARSE!";
0638     QTest::newRow("errorREF") << "C" << Value::errorREF() << "#REF!";
0639     QTest::newRow("errorVALUE") << "C" << Value::errorVALUE() << "#VALUE!";
0640 }
0641 
0642 void TestValueConverter::testAsString()
0643 {
0644     QFETCH(QString, locale);
0645     QFETCH(Value, value);
0646     QFETCH(QString, expected);
0647 
0648     *m_calcsettings->locale() = KLocale(locale, locale);
0649     QCOMPARE(m_calcsettings->locale()->country(), locale);
0650 
0651     Value result = m_converter->asString(value);
0652     QCOMPARE(result, Value(expected));
0653     QCOMPARE(m_converter->toString(value), expected);
0654 }
0655 
0656 void TestValueConverter::testAsDateTime_data()
0657 {
0658     QTest::addColumn<QString>("locale");
0659     QTest::addColumn<Value>("value");
0660     QTest::addColumn<bool>("expectedOk");
0661     QTest::addColumn<Value>("expected");
0662 
0663     // ok = true and empty value is treated as current date/time
0664     QTest::newRow("empty") << "C" << Value() << true << Value();
0665 
0666     QTest::newRow("bool true") << "C" << Value(true) << true
0667         << Value();
0668     QTest::newRow("bool false") << "C" << Value(false) << true
0669         << Value();
0670 
0671     QTest::newRow("integer") << "C" << Value(123) << true
0672         << ValueWithFormat(123.0, Value::fmt_DateTime);
0673     QTest::newRow("float") << "C" << Value(10.3) << true
0674         << ValueWithFormat(10.3, Value::fmt_DateTime);
0675     QTest::newRow("complex") << "C" << Value(complex<Number>(10.3, 12.5)) << true
0676         << ValueWithFormat(10.3, Value::fmt_DateTime);
0677 
0678     QTest::newRow("string valid") << "C" << Value("1999-11-23") << true
0679         << ValueWithFormat(-39, Value::fmt_DateTime);
0680     // TODO(mek): This should probably not have a format.
0681     QTest::newRow("string invalid") << "C" << Value("invalid") << false
0682         << ValueWithFormat(Value::errorVALUE(), Value::fmt_DateTime);
0683 
0684     ValueStorage array;
0685     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true << Value();
0686     array.insert(1, 1, Value(543.4));
0687     QTest::newRow("array 543.4") << "C" << Value(array, QSize(1, 1)) << true
0688         << ValueWithFormat(543.4, Value::fmt_DateTime);
0689     // TODO(mek): Should this one return false for ok?
0690     array.insert(1, 1, Value("invalid"));
0691     // TODO(mek): This should probably not have a format.
0692     QTest::newRow("array invalid string") << "C" << Value(array, QSize(1, 1)) << true
0693         << ValueWithFormat(Value::errorVALUE(), Value::fmt_DateTime);
0694 
0695     // TODO(mek): Are these correct?
0696     //QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << Value();
0697     //QTest::newRow("errorNA") << "C" << Value::errorNA() << true << Value();
0698 }
0699 
0700 void TestValueConverter::testAsDateTime()
0701 {
0702     QFETCH(QString, locale);
0703     QFETCH(Value, value);
0704     QFETCH(bool, expectedOk);
0705     QFETCH(Value, expected);
0706 
0707     *m_calcsettings->locale() = KLocale(locale, locale);
0708     QCOMPARE(m_calcsettings->locale()->country(), locale);
0709 
0710     bool ok;
0711     Value result = m_converter->asDateTime(value, &ok);
0712     QCOMPARE(ok, expectedOk);
0713     if (expected.isEmpty()) {
0714         QDateTime current = QDateTime::currentDateTime();
0715         expected = Value(current, m_calcsettings);
0716         QVERIFY(result.isFloat());
0717         QVERIFY(result.asFloat() <= expected.asFloat());
0718         QVERIFY(result.asFloat() >= expected.asFloat() - 1.0/(24*60*60));
0719         QCOMPARE(result.format(), expected.format());
0720     } else {
0721       qDebug() << result << " != " << expected;
0722         QCOMPARE(result, expected);
0723         QCOMPARE(result.format(), expected.format());
0724     }
0725 }
0726 
0727 void TestValueConverter::testAsDate_data()
0728 {
0729     QTest::addColumn<QString>("locale");
0730     QTest::addColumn<Value>("value");
0731     QTest::addColumn<bool>("expectedOk");
0732     QTest::addColumn<Value>("expected");
0733 
0734     QTest::newRow("empty") << "C" << Value() << true
0735         << Value(QDate::currentDate(), m_calcsettings);
0736 
0737     QTest::newRow("bool true") << "C" << Value(true) << true
0738         << Value(QDate::currentDate(), m_calcsettings);
0739     QTest::newRow("bool false") << "C" << Value(false) << true
0740         << Value(QDate::currentDate(), m_calcsettings);
0741 
0742     QTest::newRow("integer") << "C" << Value(123) << true
0743         << ValueWithFormat(123.0, Value::fmt_Date);
0744     QTest::newRow("float") << "C" << Value(10.3) << true
0745         << ValueWithFormat(10.3, Value::fmt_Date);
0746     QTest::newRow("complex") << "C" << Value(complex<Number>(10.3, 12.5)) << true
0747         << ValueWithFormat(10.3, Value::fmt_Date);
0748 
0749     QTest::newRow("string valid") << "C" << Value("2005-06-23") << true
0750         << Value(QDate(2005, 6, 23), m_calcsettings);
0751     QTest::newRow("string invalid") << "C" << Value("2005-26-23") << false
0752         << Value::errorVALUE();
0753 
0754     ValueStorage array;
0755     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true
0756         << Value(QDate::currentDate(), m_calcsettings);
0757     array.insert(1, 1, Value(543.4));
0758     QTest::newRow("array 543.4") << "C" << Value(array, QSize(1, 1)) << true
0759         << ValueWithFormat(543.4, Value::fmt_Date);
0760     // TODO(mek): Should this one return false for ok?
0761     array.insert(1, 1, Value("invalid"));
0762     QTest::newRow("array invalid string") << "C" << Value(array, QSize(1, 1)) << true
0763         << Value::errorVALUE();
0764 
0765     // TODO(mek): Are these correct?
0766     QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << Value();
0767     QTest::newRow("errorNA") << "C" << Value::errorNA() << true << Value();
0768 }
0769 
0770 void TestValueConverter::testAsDate()
0771 {
0772     QFETCH(QString, locale);
0773     QFETCH(Value, value);
0774     QFETCH(bool, expectedOk);
0775     QFETCH(Value, expected);
0776 
0777     *m_calcsettings->locale() = KLocale(locale, locale);
0778     QCOMPARE(m_calcsettings->locale()->country(), locale);
0779 
0780     bool ok;
0781     Value result = m_converter->asDate(value, &ok);
0782     QCOMPARE(ok, expectedOk);
0783     QCOMPARE(result, expected);
0784     QCOMPARE(result.format(), expected.format());
0785 }
0786 
0787 void TestValueConverter::testAsTime_data()
0788 {
0789     QTest::addColumn<QString>("locale");
0790     QTest::addColumn<Value>("value");
0791     QTest::addColumn<bool>("expectedOk");
0792     QTest::addColumn<Value>("expected");
0793 
0794     // ok = true and empty value is treated as current time
0795     QTest::newRow("empty") << "C" << Value() << true << Value();
0796 
0797     QTest::newRow("bool true") << "C" << Value(true) << true
0798         << Value();
0799     QTest::newRow("bool false") << "C" << Value(false) << true
0800         << Value();
0801 
0802     QTest::newRow("integer") << "C" << Value(123) << true
0803         << ValueWithFormat(123.0, Value::fmt_Time);
0804     QTest::newRow("float") << "C" << Value(10.3) << true
0805         << ValueWithFormat(10.3, Value::fmt_Time);
0806     QTest::newRow("complex") << "C" << Value(complex<Number>(10.3, 12.5)) << true
0807         << ValueWithFormat(10.3, Value::fmt_Time);
0808 
0809     QTest::newRow("string valid 1") << "C" << Value("13:45") << true
0810         << Value(QTime(13, 45));
0811     QTest::newRow("string valid 2") << "C" << Value("13:45:33") << true
0812         << Value(QTime(13, 45, 33));
0813     QTest::newRow("string invalid") << "C" << Value("13:66:99") << false
0814         << Value::errorVALUE();
0815 
0816     ValueStorage array;
0817     QTest::newRow("array empty") << "C" << Value(array, QSize(1, 1)) << true << Value();
0818     array.insert(1, 1, Value(543.4));
0819     QTest::newRow("array 543.4") << "C" << Value(array, QSize(1, 1)) << true
0820         << ValueWithFormat(543.4, Value::fmt_Time);
0821     // TODO(mek): Should this one return false for ok?
0822     array.insert(1, 1, Value("invalid"));
0823     QTest::newRow("array invalid string") << "C" << Value(array, QSize(1, 1)) << true
0824         << Value::errorVALUE();
0825 
0826     // TODO(mek): Are these correct?
0827     //QTest::newRow("errorCIRCLE") << "C" << Value::errorCIRCLE() << true << Value();
0828     //QTest::newRow("errorNA") << "C" << Value::errorNA() << true << Value();
0829 }
0830 
0831 void TestValueConverter::testAsTime()
0832 {
0833     QFETCH(QString, locale);
0834     QFETCH(Value, value);
0835     QFETCH(bool, expectedOk);
0836     QFETCH(Value, expected);
0837 
0838     *m_calcsettings->locale() = KLocale(locale, locale);
0839     QCOMPARE(m_calcsettings->locale()->country(), locale);
0840 
0841     bool ok;
0842     Value result = m_converter->asTime(value, &ok);
0843     QCOMPARE(ok, expectedOk);
0844     if (expected.isEmpty()) {
0845         QTime currentTime = QTime::currentTime();
0846         expected = Value(currentTime);
0847         QVERIFY(result.isFloat());
0848         QVERIFY(result.asFloat() <= expected.asFloat());
0849         QVERIFY(result.asFloat() >= expected.asFloat() - 1.0/(24*60*60));
0850         QCOMPARE(result.format(), expected.format());
0851     } else {
0852         QCOMPARE(result, expected);
0853         QCOMPARE(result.format(), expected.format());
0854     }
0855 }
0856 
0857 QTEST_MAIN(TestValueConverter)