diff options
Diffstat (limited to 'tests/yaml')
-rw-r--r-- | tests/yaml/data/cache1.yaml | 13 | ||||
-rw-r--r-- | tests/yaml/data/cache2.yaml | 14 | ||||
-rw-r--r-- | tests/yaml/data/test.yaml | 45 | ||||
-rw-r--r-- | tests/yaml/tst_yaml.cpp | 340 | ||||
-rw-r--r-- | tests/yaml/yaml.pro | 12 |
5 files changed, 424 insertions, 0 deletions
diff --git a/tests/yaml/data/cache1.yaml b/tests/yaml/data/cache1.yaml new file mode 100644 index 00000000..b3fcddb9 --- /dev/null +++ b/tests/yaml/data/cache1.yaml @@ -0,0 +1,13 @@ +name: cache1 +file: ${FILE} + +## content for a merge test +#bool: true +#list: [ 1, 2 ] +#map: +# key1: value1 +# key2: value2 +# key3: +# key31: value31 +# key32: value32 +# key4: 4 diff --git a/tests/yaml/data/cache2.yaml b/tests/yaml/data/cache2.yaml new file mode 100644 index 00000000..8ce7bae3 --- /dev/null +++ b/tests/yaml/data/cache2.yaml @@ -0,0 +1,14 @@ +name: cache2 +file: ${FILE} + +## content for a merge test +#bool: false +#list: [ 3, 4, 5 ] +#map: +# key1: value1 +# key2: not-value2 +# key3: +# key31: [ 5, 6 ] +# key32: not-value32 +# key33: true +# key5: 5 diff --git a/tests/yaml/data/test.yaml b/tests/yaml/data/test.yaml new file mode 100644 index 00000000..b16e3d39 --- /dev/null +++ b/tests/yaml/data/test.yaml @@ -0,0 +1,45 @@ +formatVersion: 42 +formatType: testfile +--- +dec: 10 +hex: 0x10 +oct: 010 +bin: 0b10 +float1: 10.10 +float2: 0.10 +float3: .10 +number-separators: 1_234_567 +bool-true: true +bool-yes: yes +bool-false: false +bool-no: no +null-literal: null +null-tilde: ~ +string-unquoted: unquoted +string-singlequoted: 'singlequoted' +string-doublequoted: "doublequoted" +list-int: +- 1 +- 2 +- 3 +list-mixed: +- 1 +- two +- [yes, ~] +map1: + a: 1 + b: two + c: [ 1, 2, 3] + +extended: + ext-string: 'ext string' + +stringlist-string: string +stringlist-list1: [ string ] +stringlist-list2: [ string1, string2 ] + +list-of-maps: +- index: 1 + name: '1' +- index: 2 + name: '2' diff --git a/tests/yaml/tst_yaml.cpp b/tests/yaml/tst_yaml.cpp new file mode 100644 index 00000000..1b53e533 --- /dev/null +++ b/tests/yaml/tst_yaml.cpp @@ -0,0 +1,340 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Copyright (C) 2019 Luxoft Sweden AB +** Copyright (C) 2018 Pelagicore AG +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the Qt Application Manager. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT-QTAS$ +** Commercial License Usage +** Licensees holding valid commercial Qt Automotive Suite licenses may use +** this file in accordance with the commercial license agreement provided +** with the Software or, alternatively, in accordance with the terms +** contained in a written agreement between you and The Qt Company. For +** licensing terms and conditions see https://www.qt.io/terms-conditions. +** For further information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore> +#include <QtTest> + +#include "qtyaml.h" +#include "configcache.h" +#include "exception.h" +#include "global.h" + +QT_USE_NAMESPACE_AM + +class tst_Yaml : public QObject +{ + Q_OBJECT + +public: + tst_Yaml(); + +private slots: + void parser(); + void documentParser(); + void cache(); + void mergedCache(); +}; + + +tst_Yaml::tst_Yaml() +{ } + +void tst_Yaml::parser() +{ + static const QVariant vnull = QVariant::fromValue(nullptr); + + QVector<QPair<const char *, QVariant>> tests = { + { "dec", QVariant::fromValue<int>(10) }, + { "hex", QVariant::fromValue<int>(16) }, + { "bin", QVariant::fromValue<int>(2) }, + { "oct", QVariant::fromValue<int>(8) }, + { "float1", QVariant::fromValue<double>(10.1) }, + { "float2", QVariant::fromValue<double>(.1) }, + { "float3", QVariant::fromValue<double>(.1) }, + { "number-separators", QVariant::fromValue<int>(1234567) }, + { "bool-true", true }, + { "bool-yes", true }, + { "bool-false", false }, + { "bool-no", false }, + { "null-literal", vnull }, + { "null-tilde", vnull }, + { "string-unquoted", QVariant::fromValue<QString>("unquoted") }, + { "string-singlequoted", QVariant::fromValue<QString>("singlequoted") }, + { "string-doublequoted", QVariant::fromValue<QString>("doublequoted") }, + { "list-int", QVariantList { 1, 2, 3 } }, + { "list-mixed", QVariantList { 1, "two", QVariantList { true, vnull } } }, + { "map1", QVariantMap { { "a", 1 }, { "b", "two" }, { "c", QVariantList { 1, 2, 3 } } } } + }; + + try { + QFile f(":/data/test.yaml"); + QVERIFY2(f.open(QFile::ReadOnly), qPrintable(f.errorString())); + QByteArray ba = f.readAll(); + QVERIFY(!ba.isEmpty()); + YamlParser p(ba); + auto header = p.parseHeader(); + + QCOMPARE(header.first, "testfile"); + QCOMPARE(header.second, 42); + + QVERIFY(p.nextDocument()); + + YamlParser::Fields fields; + for (const auto &pair : tests) { + YamlParser::FieldType type = YamlParser::Scalar; + if (pair.second.type() == QVariant::List) + type = YamlParser::List; + else if (pair.second.type() == QVariant::Map) + type = YamlParser::Map; + QVariant value = pair.second; + + fields.emplace_back(pair.first, true, type, [type, value](YamlParser *p) { + switch (type) { + case YamlParser::Scalar: { + QVERIFY(p->isScalar()); + QVariant v = p->parseScalar(); + QCOMPARE(int(v.type()), int(value.type())); + QVERIFY(v == value); + break; + } + case YamlParser::List: { + QVERIFY(p->isList()); + QVariantList vl = p->parseList(); + QVERIFY(vl == value.toList()); + break; + } + case YamlParser::Map: { + QVERIFY(p->isMap()); + QVariantMap vm = p->parseMap(); + QVERIFY(vm == value.toMap()); + break; + } + } + }); + } + fields.emplace_back("extended", true, YamlParser::Map, [](YamlParser *p) { + YamlParser::Fields extFields = { + { "ext-string", true, YamlParser::Scalar, [](YamlParser *p) { + QVERIFY(p->isScalar()); + QVariant v = p->parseScalar(); + QCOMPARE(v.type(), QVariant::String); + QCOMPARE(v.toString(), "ext string"); + } } + }; + p->parseFields(extFields); + }); + + fields.emplace_back("stringlist-string", true, YamlParser::Scalar | YamlParser::List, [](YamlParser *p) { + QCOMPARE(p->parseStringOrStringList(), QStringList { "string" }); + }); + fields.emplace_back("stringlist-list1", true, YamlParser::Scalar | YamlParser::List, [](YamlParser *p) { + QCOMPARE(p->parseStringOrStringList(), QStringList { "string" }); + }); + fields.emplace_back("stringlist-list2", true, YamlParser::Scalar | YamlParser::List, [](YamlParser *p) { + QCOMPARE(p->parseStringOrStringList(), QStringList({ "string1", "string2" })); + }); + + fields.emplace_back("list-of-maps", true, YamlParser::List, [](YamlParser *p) { + int index = 0; + p->parseList([&index](YamlParser *p) { + ++index; + YamlParser::Fields lomFields = { + { "index", true, YamlParser::Scalar, [&index](YamlParser *p) { + QCOMPARE(p->parseScalar().toInt(), index); + } }, + { "name", true, YamlParser::Scalar, [&index](YamlParser *p) { + QCOMPARE(p->parseScalar().toString(), QString::number(index)); + } } + }; + p->parseFields(lomFields); + }); + QCOMPARE(index, 2); + }); + + p.parseFields(fields); + + QVERIFY(!p.nextDocument()); + + } catch (const Exception &e) { + QVERIFY2(false, e.what()); + } +} + +void tst_Yaml::documentParser() +{ + static const QVariant vnull = QVariant::fromValue(nullptr); + + try { + QFile f(":/data/test.yaml"); + QVERIFY2(f.open(QFile::ReadOnly), qPrintable(f.errorString())); + QByteArray ba = f.readAll(); + QVERIFY(!ba.isEmpty()); + QVector<QVariant> docs = YamlParser::parseAllDocuments(ba); + QCOMPARE(docs.size(), 2); + QCOMPARE(docs.at(0).toMap().size(), 2); + + QVariantMap header = { + { "formatVersion", 42 }, { "formatType", "testfile" } + }; + + QVariantMap main = { + { "dec", 10 }, + { "hex", 16 }, + { "bin", 2 }, + { "oct", 8 }, + { "float1", 10.1 }, + { "float2", .1 }, + { "float3", .1 }, + { "number-separators", 1234567 }, + { "bool-true", true }, + { "bool-yes", true }, + { "bool-false", false }, + { "bool-no", false }, + { "null-literal", vnull }, + { "null-tilde", vnull }, + { "string-unquoted", "unquoted" }, + { "string-singlequoted", "singlequoted" }, + { "string-doublequoted", "doublequoted" }, + { "list-int", QVariantList { 1, 2, 3 } }, + { "list-mixed", QVariantList { 1, qSL("two"), QVariantList { true, vnull } } }, + { "map1", QVariantMap { { "a", 1 }, { "b", "two" }, { "c", QVariantList { 1, 2, 3 } } } }, + + + { "extended", QVariantMap { { "ext-string", "ext string" } } }, + + { "stringlist-string", "string" }, + { "stringlist-list1", QVariantList { "string" } }, + { "stringlist-list2", QVariantList { "string1", "string2" } }, + + { "list-of-maps", QVariantList { QVariantMap { { "index", 1 }, { "name", "1" } }, + QVariantMap { { "index", 2 }, { "name", "2" } } } } + }; + + QCOMPARE(header, docs.at(0).toMap()); + QCOMPARE(main, docs.at(1).toMap()); + + } catch (const Exception &e) { + QVERIFY2(false, e.what()); + } +} +struct CacheTest +{ + QString name; + QString file; +}; + +// GCC < 7 bug, currently still in RHEL7, https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480 +// this should simply be: +// template<> class QT_PREPEND_NAMESPACE_AM(ConfigCacheAdaptor<CacheTest>) + +QT_BEGIN_NAMESPACE_AM +template<> class ConfigCacheAdaptor<CacheTest> +{ +public: + CacheTest *loadFromSource(QIODevice *source, const QString &fileName) + { + QScopedPointer<CacheTest> ct(new CacheTest); + YamlParser p(source->readAll(), fileName); + p.nextDocument(); + p.parseFields({ { "name", true, YamlParser::Scalar, [&ct](YamlParser *p) { + ct->name = p->parseScalar().toString(); } }, + { "file", true, YamlParser::Scalar, [&ct](YamlParser *p) { + ct->file = p->parseScalar().toString(); } } + }); + return ct.take(); + } + CacheTest *loadFromCache(QDataStream &ds) + { + CacheTest *ct = new CacheTest; + ds >> ct->name >> ct->file; + return ct; + } + void saveToCache(QDataStream &ds, const CacheTest *ct) + { + ds << ct->name << ct->file; + } + + void merge(CacheTest *ct1, const CacheTest *ct2) + { + ct1->name = ct2->name; + ct1->file = ct1->file + qSL(",") + ct2->file; + } + void preProcessSourceContent(QByteArray &sourceContent, const QString &fileName) + { + sourceContent.replace("${FILE}", fileName.toUtf8()); + } + QStringList *warnings; +}; +QT_END_NAMESPACE_AM + +void tst_Yaml::cache() +{ + QStringList files = { ":/data/cache1.yaml", ":/data/cache2.yaml" }; + QStringList warnings; + + for (int step = 0; step < 2; ++step) { + try { + ConfigCache<CacheTest> cache(files, "cache-test", step == 0 ? AbstractConfigCache::ClearCache + : AbstractConfigCache::None); + cache.parse(&warnings); + QVERIFY2(warnings.isEmpty(), qPrintable(warnings.join(qSL("\n")))); + CacheTest *ct1 = cache.takeResult(0); + QVERIFY(ct1); + QCOMPARE(ct1->name, "cache1"); + QCOMPARE(ct1->file, ":/data/cache1.yaml"); + CacheTest *ct2 = cache.takeResult(1); + QVERIFY(ct2); + QCOMPARE(ct2->name, "cache2"); + QCOMPARE(ct2->file, ":/data/cache2.yaml"); + } catch (const Exception &e) { + QVERIFY2(false, e.what()); + } + } +} + +void tst_Yaml::mergedCache() +{ + QStringList files = { ":/data/cache1.yaml", ":/data/cache2.yaml" }; + QStringList warnings; + + for (int step = 0; step < 4; ++step) { + AbstractConfigCache::Options options = AbstractConfigCache::MergedResult; + if (step % 2 == 0) + options |= AbstractConfigCache::ClearCache; + if (step == 2) + std::reverse(files.begin(), files.end()); + + try { + ConfigCache<CacheTest> cache(files, "cache-test", options); + cache.parse(&warnings); + QVERIFY2(warnings.isEmpty(), qPrintable(warnings.join(qSL("\n")))); + CacheTest *ct = cache.takeMergedResult(); + QVERIFY(ct); + QCOMPARE(ct->name, QFileInfo(files.last()).baseName()); + QCOMPARE(ct->file, files.join(qSL(","))); + } catch (const Exception &e) { + QVERIFY2(false, e.what()); + } + } +} + +QTEST_MAIN(tst_Yaml) + +#include "tst_yaml.moc" diff --git a/tests/yaml/yaml.pro b/tests/yaml/yaml.pro new file mode 100644 index 00000000..5cc4bbb5 --- /dev/null +++ b/tests/yaml/yaml.pro @@ -0,0 +1,12 @@ +TARGET = tst_yaml + +include($$PWD/../tests.pri) + +QT *= appman_common-private + +SOURCES += tst_yaml.cpp + +RESOURCES += \ + data/test.yaml \ + data/cache1.yaml \ + data/cache2.yaml \ |