File indexing completed on 2024-05-12 05:17:31
0001 /* 0002 SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "testhelpers.h" 0008 0009 #include <KItinerary/Flight> 0010 #include <KItinerary/JsonLdDocument> 0011 #include <KItinerary/MergeUtil> 0012 #include <KItinerary/Organization> 0013 #include <KItinerary/Person> 0014 #include <KItinerary/Reservation> 0015 #include <KItinerary/TrainTrip> 0016 0017 #include <QDateTime> 0018 #include <QDebug> 0019 #include <QFile> 0020 #include <QJsonArray> 0021 #include <QJsonDocument> 0022 #include <QJsonObject> 0023 #include <QObject> 0024 #include <QTest> 0025 0026 #define _(x) QStringLiteral(x) 0027 0028 using namespace KItinerary; 0029 0030 class MergeUtilTest : public QObject 0031 { 0032 Q_OBJECT 0033 private: 0034 QByteArray readFile(const QString &fn) const 0035 { 0036 QFile f(fn); 0037 f.open(QFile::ReadOnly); 0038 return f.readAll(); 0039 } 0040 0041 private Q_SLOTS: 0042 void testIsSameReservation() 0043 { 0044 QVERIFY(!MergeUtil::isSame({}, {})); 0045 FlightReservation res1; 0046 QVERIFY(!MergeUtil::isSame(res1, {})); 0047 QVERIFY(!MergeUtil::isSame({}, res1)); 0048 0049 res1.setReservationNumber(QStringLiteral("XXX007")); 0050 Flight flight1; 0051 flight1.setFlightNumber(QStringLiteral("1234")); 0052 flight1.setDepartureDay(QDate(2018, 4, 21)); 0053 res1.setReservationFor(flight1); 0054 0055 FlightReservation res2; 0056 res2.setReservationNumber(QStringLiteral("YYY008")); 0057 Flight flight2; 0058 flight2.setFlightNumber(QStringLiteral("1234")); 0059 res2.setReservationFor(flight2); 0060 QVERIFY(!MergeUtil::isSame(res1, res2)); 0061 0062 flight2.setDepartureDay(QDate(2018, 4, 21)); 0063 res2.setReservationFor(flight2); 0064 QVERIFY(MergeUtil::isSame(flight2, res2.reservationFor())); 0065 QVERIFY(!MergeUtil::isSame(res1, res2)); 0066 0067 res2.setReservationNumber(QStringLiteral("XXX007")); 0068 QVERIFY(MergeUtil::isSame(flight1, flight2)); 0069 QVERIFY(MergeUtil::isSame(res1.reservationFor(), res2.reservationFor())); 0070 QVERIFY(MergeUtil::isSame(res1, res2)); 0071 } 0072 0073 void testIsSameFlight() 0074 { 0075 Airline airline1; 0076 airline1.setIataCode(QStringLiteral("KL")); 0077 Flight f1; 0078 f1.setAirline(airline1); 0079 f1.setFlightNumber(QStringLiteral("8457")); 0080 f1.setDepartureTime(QDateTime(QDate(2018, 4, 2), QTime(17, 51, 0))); 0081 0082 Flight f2; 0083 QVERIFY(!MergeUtil::isSame(f1, f2)); 0084 0085 f2.setFlightNumber(QStringLiteral("8457")); 0086 QVERIFY(!MergeUtil::isSame(f1, f2)); 0087 0088 Airline airline2; 0089 airline2.setIataCode(QStringLiteral("AF")); 0090 f2.setAirline(airline2); 0091 QVERIFY(!MergeUtil::isSame(f1, f2)); 0092 airline2.setIataCode(QStringLiteral("KL")); 0093 f2.setAirline(airline2); 0094 QVERIFY(MergeUtil::isSame(f1, f2)); 0095 0096 f2.setDepartureDay(QDate(2018, 4, 2)); 0097 QVERIFY(MergeUtil::isSame(f1, f2)); 0098 f2.setDepartureDay(QDate(2018, 4, 3)); 0099 QVERIFY(!MergeUtil::isSame(f1, f2)); 0100 } 0101 0102 void testCodeShareFlight() 0103 { 0104 Airline a1; 0105 a1.setIataCode(QStringLiteral("4U")); 0106 Flight f1; 0107 f1.setAirline(a1); 0108 f1.setFlightNumber(QStringLiteral("42")); 0109 f1.setDepartureDay(QDate(2018, 04, 21)); 0110 0111 Airline a2; 0112 a2.setIataCode(QStringLiteral("EW")); 0113 Flight f2(f1); 0114 f2.setAirline(a2); 0115 0116 QVERIFY(MergeUtil::isSame(f1, f2)); 0117 } 0118 0119 void testIsSamePerson_data() 0120 { 0121 // we do not need to consider cases here that ExtractorPostprocessor eliminates for us 0122 // such as filling the full name or honoric prefixes 0123 QTest::addColumn<QList<QStringList>>("data"); 0124 0125 QTest::newRow("simple name") << QList<QStringList>{ 0126 {_("Volker Krause"), {}, {}}, 0127 {_("VOLKER KRAUSE"), {}, {}}, 0128 {_("VOLKER KRAUSE"), _("Volker"), _("Krause")}, 0129 {_("VOLKER KRAUSE"), {}, _("Krause")}, 0130 {_("VOLKER KRAUSE"), _("Volker"), {}}, 0131 // IATA BCBP artifacts 0132 {_("VOLKERMR KRAUSE"), _("VOLKERMR"), _("KRAUSE")}, 0133 {_("VOLKER MR KRAUSE"), _("VOLKER MR"), _("KRAUSE")}}; 0134 0135 QTest::newRow("double family name") << QList<QStringList>{ 0136 {_("Andreas Cord-Landwehr"), {}, {}}, 0137 {_("ANDREAS CORD-LANDWEHR"), {}, {}}, 0138 {_("ANDREAS CORD-LANDWEHR"), _("Andreas"), _("Cord-Landwehr")}, 0139 // IATA BCBP artifacts 0140 {_("Andreas Cordlandwehr"), {}, {}}, 0141 {_("ANDREAS CORDLANDWEHR"), _("ANDREAS"), _("CORDLANDWEHR")}, 0142 {_("ANDREAS CORD LANDWEHR"), _("ANDREAS"), _("CORD LANDWEHR")}, 0143 {_("ANDREAS CORD LANDWEHR"), {}, {}}}; 0144 0145 QTest::newRow("diacritic") << QList<QStringList>{ 0146 {_("Daniel Vrátil"), {}, {}}, 0147 {_("Daniel Vrátil"), _("Daniel"), _("Vrátil")}, 0148 {_("DANIEL VRATIL"), {}, {}}, 0149 {_("DANIEL VRATIL"), _("DANIEL"), _("VRATIL")}}; 0150 0151 QTest::newRow("transliteration") << QList<QStringList>{ 0152 {_("Bjärn Lastname"), {}, {}}, 0153 {_("BJAERN LASTNAME"), _("BJAERN"), _("LASTNAME")}, 0154 }; 0155 0156 QTest::newRow("partial") << QList<QStringList> { 0157 {_("VOLKER KRAUSE"), _("Volker"), _("Krause")}, 0158 {_("KRAUSE"),{}, {}} 0159 }; 0160 0161 QTest::newRow("double given name") << QList<QStringList> { 0162 {_("Kai Uwe Broulik"), _("Kai Uwe"), _("Broulik")}, 0163 {_("Kai Broulik"), _("Kai"), _("Broulik")}, 0164 }; 0165 } 0166 0167 void testIsSamePerson() 0168 { 0169 QFETCH(QList<QStringList>, data); 0170 0171 for(int i = 0; i < data.size(); ++i) { 0172 Person lhs; 0173 lhs.setName(data[i][0]); 0174 lhs.setGivenName(data[i][1]); 0175 lhs.setFamilyName(data[i][2]); 0176 0177 for (int j = 0; j < data.size(); ++j) { 0178 Person rhs; 0179 rhs.setName(data[j][0]); 0180 rhs.setGivenName(data[j][1]); 0181 rhs.setFamilyName(data[j][2]); 0182 0183 QVERIFY(!MergeUtil::isSamePerson(lhs, {})); 0184 QVERIFY(!MergeUtil::isSamePerson({}, lhs)); 0185 0186 if (!MergeUtil::isSamePerson(lhs, rhs)) { 0187 qDebug() << "Left: " << lhs.name() << lhs.givenName() << lhs.familyName(); 0188 qDebug() << "Right: " << rhs.name() << rhs.givenName() << rhs.familyName(); 0189 } 0190 QVERIFY(MergeUtil::isSamePerson(lhs, rhs)); 0191 } 0192 } 0193 } 0194 0195 void testIsNotSamePerson() 0196 { 0197 QList<QStringList> data{ 0198 {_("Volker Krause"), {}, {}}, 0199 {_("Andreas Cord-Landwehr"), _("Andread"), _("Cord-Landwehr")}, 0200 {_("GIVEN1 GIVEN2 FAMILY1"), {}, {}}, 0201 {_("V K"), {}, {}}, 0202 {_("Daniel Vrátil"), _("Daniel"), _("Vrátil")}, 0203 }; 0204 0205 for(int i = 0; i < data.size(); ++i) { 0206 Person lhs; 0207 lhs.setName(data[i][0]); 0208 lhs.setGivenName(data[i][1]); 0209 lhs.setFamilyName(data[i][2]); 0210 0211 for (int j = 0; j < data.size(); ++j) { 0212 if (i == j) { 0213 continue; 0214 } 0215 0216 Person rhs; 0217 rhs.setName(data[j][0]); 0218 rhs.setGivenName(data[j][1]); 0219 rhs.setFamilyName(data[j][2]); 0220 0221 QVERIFY(!MergeUtil::isSamePerson(lhs, {})); 0222 QVERIFY(!MergeUtil::isSamePerson({}, lhs)); 0223 0224 if (MergeUtil::isSamePerson(lhs, rhs)) { 0225 qDebug() << "Left: " << lhs.name() << lhs.givenName() << lhs.familyName(); 0226 qDebug() << "Right: " << rhs.name() << rhs.givenName() << rhs.familyName(); 0227 } 0228 QVERIFY(!MergeUtil::isSamePerson(lhs, rhs)); 0229 } 0230 } 0231 } 0232 0233 void testIsSameTrain_data() 0234 { 0235 QTest::addColumn<QString>("lhsName"); 0236 QTest::addColumn<QString>("lhsNumber"); 0237 QTest::addColumn<QString>("rhsName"); 0238 QTest::addColumn<QString>("rhsNumber"); 0239 QTest::addColumn<bool>("shouldBeSame"); 0240 0241 QTest::newRow("empty") << QString() << QString() << QString() << QString() << false; 0242 QTest::newRow("equal number") << QString() << _("123") << QString() << _("123") << true; 0243 QTest::newRow("optional name") << QString() << _("123") << _("EC") << _("123") << true; 0244 QTest::newRow("optional name2") << QString() << _("123") << QString() << _("EC 123") << true; 0245 QTest::newRow("name mismatch") << _("IC") << _("123") << _("EC") << _("123") << false; 0246 QTest::newRow("name mismatch2") << QString() << _("IC 123") << QString() << _("EC 123") << false; 0247 QTest::newRow("number mismatch") << QString() << _("123") << QString() << _("234") << false; 0248 QTest::newRow("number prefix") << QString() << _("123") << QString() << _("12") << false; 0249 QTest::newRow("number prefix2") << QString() << _("123") << QString() << _("23") << false; 0250 0251 QTest::newRow("train-and-line-number-0") << QString() << _("RE 13 (20070)") << QString() << _("RE 13 (20072)") << false; 0252 QTest::newRow("train-and-line-number-1") << QString() << _("RE 13 (20070)") << QString() << _("RE 20070") << true; 0253 QTest::newRow("train-and-line-number-2") << QString() << _("RE 13 (20070)") << QString() << _("RE 13") << true; 0254 //QTest::newRow("train-and-line-number-3") << QString() << _("RE 13 (20070)") << QString() << _("RE") << false; 0255 QTest::newRow("train-and-line-number-4") << QString() << _("RB 33 (10323)") << QString() << _("RE 33") << false; 0256 QTest::newRow("train-and-line-number-5") << QString() << _("RB 33 (10323)") << QString() << _("RE 10323") << false; 0257 QTest::newRow("train-and-line-number-6") << QString() << _("RB 33 (10323)") << QString() << _("RB 10323") << true; 0258 QTest::newRow("train-and-line-number-7") << QString() << _("RB 33 (10323)") << QString() << _("RB 33") << true; 0259 QTest::newRow("train-and-line-number-8") << QString() << _("RB 33 (10323)") << QString() << _("RB 23") << false; 0260 QTest::newRow("train-and-line-number-9") << QString() << _("RB 33 (10323)") << QString() << _("RB 23 (10323)") << false; 0261 } 0262 0263 void testIsSameTrain() 0264 { 0265 QFETCH(QString, lhsName); 0266 QFETCH(QString, lhsNumber); 0267 QFETCH(QString, rhsName); 0268 QFETCH(QString, rhsNumber); 0269 QFETCH(bool, shouldBeSame); 0270 0271 TrainTrip lhs; 0272 lhs.setDepartureTime(QDateTime({2019, 11, 9}, {12, 00})); 0273 lhs.setTrainName(lhsName); 0274 lhs.setTrainNumber(lhsNumber); 0275 0276 TrainTrip rhs; 0277 rhs.setDepartureTime(QDateTime({2019, 11, 9}, {12, 00})); 0278 rhs.setTrainName(rhsName); 0279 rhs.setTrainNumber(rhsNumber); 0280 0281 QCOMPARE(MergeUtil::isSame(lhs, rhs), shouldBeSame); 0282 QCOMPARE(MergeUtil::isSame(rhs, lhs), shouldBeSame); 0283 } 0284 0285 void testIsSameLodingReservation() 0286 { 0287 LodgingReservation res1; 0288 LodgingBusiness hotel1; 0289 hotel1.setName(QStringLiteral("Haus Randa")); 0290 res1.setReservationFor(hotel1); 0291 res1.setCheckinTime(QDateTime(QDate(2018, 4, 9), QTime(10, 0))); 0292 res1.setReservationNumber(QStringLiteral("1234")); 0293 0294 LodgingReservation res2; 0295 QVERIFY(!MergeUtil::isSame(res1, res2)); 0296 res2.setReservationNumber(QStringLiteral("1234")); 0297 QVERIFY(!MergeUtil::isSame(res1, res2)); 0298 res2.setCheckinTime(QDateTime(QDate(2018, 4, 9), QTime(15, 0))); 0299 QVERIFY(!MergeUtil::isSame(res1, res2)); 0300 LodgingBusiness hotel2; 0301 hotel2.setName(QStringLiteral("Haus Randa")); 0302 res2.setReservationFor(hotel2); 0303 QVERIFY(MergeUtil::isSame(res1, res2)); 0304 } 0305 0306 void testIsSameCancellation() 0307 { 0308 const auto lhs = JsonLdDocument::fromJson(QJsonDocument::fromJson(readFile(_(SOURCE_DIR "/mergedata/cancellation.lhs.json"))).array()); 0309 const auto rhs = JsonLdDocument::fromJson(QJsonDocument::fromJson(readFile(_(SOURCE_DIR "/mergedata/cancellation.rhs.json"))).array()); 0310 QCOMPARE(lhs.size(), 1); 0311 QCOMPARE(rhs.size(), 1); 0312 QVERIFY(MergeUtil::isSame(lhs[0], rhs[0])); 0313 } 0314 0315 void testMerge_data() 0316 { 0317 QTest::addColumn<QString>("baseName"); 0318 0319 QDir dir(QStringLiteral(SOURCE_DIR "/mergedata")); 0320 const auto lst = dir.entryList(QStringList(QStringLiteral("*.merged.json")), QDir::Files | QDir::Readable | QDir::NoSymLinks); 0321 for (const auto &file : lst) { 0322 const auto base = file.left(file.size() - 12); 0323 QTest::newRow(base.toLatin1().constData()) << (dir.path() + QLatin1Char('/') + base); 0324 } 0325 } 0326 0327 void testMerge() 0328 { 0329 QFETCH(QString, baseName); 0330 0331 const auto lhs = 0332 JsonLdDocument::fromJson( 0333 QJsonDocument::fromJson( 0334 readFile(baseName + QLatin1StringView(".lhs.json"))) 0335 .array()) 0336 .first(); 0337 const auto rhs = 0338 JsonLdDocument::fromJson( 0339 QJsonDocument::fromJson( 0340 readFile(baseName + QLatin1StringView(".rhs.json"))) 0341 .array()) 0342 .first(); 0343 const auto expected = QJsonDocument::fromJson( 0344 readFile(baseName + QLatin1StringView(".merged.json"))); 0345 0346 const auto mergedL2R = MergeUtil::merge(lhs, rhs); 0347 auto mergedJson = 0348 QJsonDocument(JsonLdDocument::toJson(QList<QVariant>({mergedL2R}))); 0349 if (mergedJson != expected) { 0350 Test::compareJson(baseName + QLatin1StringView(".merged.json"), 0351 mergedJson, expected); 0352 } 0353 QCOMPARE(mergedJson, expected); 0354 0355 const auto mergedR2L = MergeUtil::merge(rhs, lhs); 0356 mergedJson = 0357 QJsonDocument(JsonLdDocument::toJson(QList<QVariant>({mergedR2L}))); 0358 if (mergedJson != expected) { 0359 Test::compareJson(baseName + QLatin1StringView(".merged.json"), 0360 mergedJson, expected); 0361 } 0362 QCOMPARE(mergedJson, expected); 0363 } 0364 0365 void testIsSameIncidence() 0366 { 0367 const auto lhsFlight = 0368 JsonLdDocument::fromJson( 0369 QJsonDocument::fromJson( 0370 readFile(QLatin1StringView( 0371 SOURCE_DIR "/calendarhandlerdata/flight.json"))) 0372 .array()) 0373 .first() 0374 .value<FlightReservation>(); 0375 auto rhsFlight = lhsFlight; 0376 Person p = rhsFlight.underName().value<Person>(); 0377 p.setName(QLatin1StringView("Jane Doe")); 0378 rhsFlight.setUnderName(p); 0379 QVERIFY(!MergeUtil::isSame(lhsFlight, rhsFlight)); 0380 QVERIFY(MergeUtil::isSameIncidence(lhsFlight, rhsFlight)); 0381 0382 const auto lhsHotel = 0383 JsonLdDocument::fromJson( 0384 QJsonDocument::fromJson( 0385 readFile(QLatin1StringView( 0386 SOURCE_DIR "/calendarhandlerdata/hotel.json"))) 0387 .array()) 0388 .first() 0389 .value<LodgingReservation>(); 0390 auto rhsHotel = lhsHotel; 0391 p = rhsHotel.underName().value<Person>(); 0392 p.setName(QLatin1StringView("Jane Doe")); 0393 rhsHotel.setUnderName(p); 0394 QVERIFY(!MergeUtil::isSame(lhsHotel, rhsHotel)); 0395 QVERIFY(MergeUtil::isSameIncidence(lhsHotel, rhsHotel)); 0396 rhsHotel.setCheckinTime(rhsHotel.checkoutTime().addDays(2)); 0397 QVERIFY(!MergeUtil::isSame(lhsHotel, rhsHotel)); 0398 QVERIFY(!MergeUtil::isSameIncidence(lhsHotel, rhsHotel)); 0399 } 0400 }; 0401 0402 QTEST_APPLESS_MAIN(MergeUtilTest) 0403 0404 #include "mergeutiltest.moc"