File indexing completed on 2024-12-08 07:18:33

0001 /*
0002     SPDX-FileCopyrightText: 2020 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include <map/content/platformfinder_p.h>
0008 
0009 #include <KOSMIndoorMap/MapData>
0010 #include <KOSMIndoorMap/MapLoader>
0011 
0012 #include <QMetaEnum>
0013 #include <QProcess>
0014 #include <QTest>
0015 #include <QtPlugin>
0016 
0017 Q_IMPORT_PLUGIN(OSM_XmlIOPlugin)
0018 
0019 using namespace KOSMIndoorMap;
0020 
0021 class PlatformFinderTest : public QObject
0022 {
0023     Q_OBJECT
0024 private:
0025     void writeElement(QIODevice *device, OSM::Element elem)
0026     {
0027         switch (elem.type()) {
0028             case OSM::Type::Null:
0029                 device->write("<null>");
0030                 break;
0031             case OSM::Type::Node:
0032                 device->write("n" + QByteArray::number((qlonglong)elem.id()));
0033                 break;
0034             case OSM::Type::Way:
0035                 if (elem.id() >= 0) {
0036                     device->write("w" + QByteArray::number((qlonglong)elem.id()));
0037                 } else {
0038                     device->write("<synthetic way>");
0039                 }
0040                 break;
0041             case OSM::Type::Relation:
0042                 if (elem.id() >= 0) {
0043                     device->write("r" + QByteArray::number((qlonglong)elem.id()));
0044                 } else {
0045                     device->write("<synthetic relation>");
0046                 }
0047                 break;
0048         }
0049     }
0050     void writeElement(QIODevice *device, const std::vector<OSM::Element> elems)
0051     {
0052         if (elems.size() == 1) {
0053             writeElement(device, elems[0]);
0054             return;
0055         }
0056 
0057         device->write("[");
0058         for (auto e : elems) {
0059             writeElement(device, e);
0060             device->write(" ");
0061         }
0062         device->write("]");
0063     }
0064 
0065 private Q_SLOTS:
0066     void initTestCase()
0067     {
0068         QLocale::setDefault(QLocale(QLocale::English, QLocale::LatinScript, QLocale::UnitedStates));
0069     }
0070 
0071     void testPlatformFinder_data()
0072     {
0073         QTest::addColumn<QString>("input");
0074         QTest::addColumn<QString>("expected");
0075 
0076         // has platform_edge and platform section tags
0077         QTest::newRow("hamburg-altona") << (SOURCE_DIR "/data/platforms/hamburg-altona.osm") << (SOURCE_DIR "/data/platforms/hamburg-altona.platforms");
0078         // has no platform edges, but platform sections
0079         QTest::newRow("cologne-central") << (SOURCE_DIR "/data/platforms/cologne-central.osm") << (SOURCE_DIR "/data/platforms/cologne-central.platforms");
0080         // numberic and non-numeric platform names, free-floating sections with a non-standard encoding, no edges, partly no stop points
0081         QTest::newRow("paris-gare-de-lyon") << (SOURCE_DIR "/data/platforms/paris-gare-de-lyon.osm") << (SOURCE_DIR "/data/platforms/paris-gare-de-lyon.platforms");
0082         // multiple modes, 3 levels, no sections, multiple stop points on the same track
0083         QTest::newRow("berlin-central") << (SOURCE_DIR "/data/platforms/berlin-central.osm") << (SOURCE_DIR "/data/platforms/berlin-central.platforms");
0084         // split areas/edges, edges on the wrong level, triple platforms
0085         QTest::newRow("leipzig-central") << (SOURCE_DIR "/data/platforms/leipzig-central.osm") << (SOURCE_DIR "/data/platforms/leipzig-central.platforms");
0086         // multiple stop points per track, no edges, up to 4 split tracks
0087         QTest::newRow("hamburg-central") << (SOURCE_DIR "/data/platforms/hamburg-central.osm") << (SOURCE_DIR "/data/platforms/hamburg-central.platforms");
0088     }
0089 
0090     void testPlatformFinder()
0091     {
0092         QFETCH(QString, input);
0093         QFETCH(QString, expected);
0094 
0095         MapLoader loader;
0096         loader.loadFromFile(input);
0097         QCOMPARE(loader.isLoading(), false);
0098         QCOMPARE(loader.hasError(), false);
0099 
0100         const auto mapData = loader.takeData();
0101         QVERIFY(!mapData.dataSet().nodes.empty());
0102         QVERIFY(!mapData.dataSet().ways.empty());
0103         QVERIFY(!mapData.dataSet().relations.empty());
0104         QVERIFY(mapData.boundingBox().height() > 0);
0105         QVERIFY(mapData.boundingBox().width() > 0);
0106 
0107         PlatformFinder finder;
0108         const auto result = finder.find(mapData);
0109         QVERIFY(!result.empty());
0110 
0111         QFile outFile(QFileInfo(expected).fileName());
0112         QVERIFY(outFile.open(QFile::ReadWrite | QFile::Truncate | QFile::Text));
0113 
0114         for (const auto &platform : result) {
0115             outFile.write(platform.name().toUtf8() + "\n");
0116             outFile.write("  position: " + QByteArray::number(platform.position().latitude) + " " + QByteArray::number(platform.position().longitude) + "\n");
0117             outFile.write("  stop point: ");
0118             writeElement(&outFile, platform.stopPoint());
0119             outFile.write("\n");
0120             outFile.write("  edge: ");
0121             writeElement(&outFile, platform.edge());
0122             outFile.write("\n");
0123             outFile.write("  area: ");
0124             writeElement(&outFile, platform.area());
0125             outFile.write("\n");
0126             outFile.write("  track: ");
0127             writeElement(&outFile, platform.track());
0128             outFile.write("\n");
0129             outFile.write("  level: " + QByteArray::number(platform.level()) + "\n");
0130             outFile.write(QByteArray("  mode: ") + Platform::staticMetaObject.enumerator(0).valueToKey(platform.mode()) + "\n");
0131             if (!platform.lines().empty()) {
0132                 outFile.write("  lines: " + platform.lines().join(QLatin1Char('|')).toUtf8() + "\n");
0133             }
0134             if (!platform.sections().empty()) {
0135                 outFile.write("  sections:\n");
0136                 for (const auto &section : platform.sections()) {
0137                     outFile.write("    name: " + section.name().toUtf8() + "\n");
0138                     outFile.write("    position: ");
0139                     writeElement(&outFile, section.position());
0140                     outFile.write("\n");
0141                 }
0142             }
0143         }
0144         outFile.seek(0);
0145         const auto platforms = outFile.readAll();
0146 
0147         QFile expectedFile(expected);
0148         QVERIFY(expectedFile.open(QFile::ReadOnly | QFile::Text));
0149         const auto expectedPlatforms = expectedFile.readAll();
0150 
0151         if (platforms != expectedPlatforms) {
0152             QProcess proc;
0153             proc.setProcessChannelMode(QProcess::ForwardedChannels);
0154             proc.start(QStringLiteral("diff"), {QStringLiteral("-u"), expectedFile.fileName(), outFile.fileName()});
0155             proc.waitForFinished();
0156         }
0157         QVERIFY(platforms == expectedPlatforms);
0158     }
0159 };
0160 
0161 QTEST_GUILESS_MAIN(PlatformFinderTest)
0162 
0163 #include "platformfindertest.moc"