File indexing completed on 2024-05-19 05:17:50

0001 /*
0002     SPDX-FileCopyrightText: 2018 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include <KItinerary/Flight>
0008 #include <KItinerary/JsonLdDocument>
0009 #include <KItinerary/Organization>
0010 #include <KItinerary/Place>
0011 #include <KItinerary/Reservation>
0012 #include <KItinerary/Person>
0013 #include <KItinerary/Taxi>
0014 #include <KItinerary/RentalCar>
0015 #include <KItinerary/Brand>
0016 
0017 #include <QDebug>
0018 #include <QJsonArray>
0019 #include <QJsonDocument>
0020 #include <QJsonObject>
0021 #include <QObject>
0022 #include <QProcess>
0023 #include <QTest>
0024 #include <QTimeZone>
0025 
0026 using namespace KItinerary;
0027 
0028 class JsonLdDocumentTest : public QObject
0029 {
0030     Q_OBJECT
0031 private:
0032     QByteArray readFile(const QString &fn)
0033     {
0034         QFile f(fn);
0035         f.open(QFile::ReadOnly);
0036         return f.readAll();
0037     }
0038 
0039 private Q_SLOTS:
0040     void initTestCase()
0041     {
0042         qputenv("TZ", "America/Chicago");
0043     }
0044 
0045     void testSerialization()
0046     {
0047         Flight f;
0048         f.setFlightNumber(QStringLiteral("1234"));
0049         f.setDepartureTime(QDateTime(QDate(2018, 3, 18), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0050         f.setDepartureDay(QDate(2018, 3, 18));
0051         f.setArrivalTime(QDateTime(QDate(2018, 3, 18), QTime(19, 44, 0), QTimeZone::UTC));
0052         Airport ap;
0053         ap.setName(QStringLiteral("Berlin Tegel"));
0054         ap.setIataCode(QStringLiteral("TXL"));
0055         f.setDepartureAirport(ap);
0056         f.setDepartureGate(QLatin1StringView(""));
0057         Airline airline;
0058         airline.setIataCode(QStringLiteral("LH"));
0059         f.setAirline(airline);
0060 
0061         auto array =
0062             JsonLdDocument::toJson(QList<QVariant>({QVariant::fromValue(f)}));
0063         QCOMPARE(array.size(), 1);
0064         auto obj = array.at(0).toObject();
0065         QCOMPARE(obj.value(QLatin1StringView("@context")).toString(),
0066                  QLatin1String("http://schema.org"));
0067         QCOMPARE(obj.value(QLatin1StringView("@type")).toString(),
0068                  QLatin1String("Flight"));
0069         QCOMPARE(obj.value(QLatin1StringView("flightNumber")).toString(),
0070                  QLatin1String("1234"));
0071 
0072         QCOMPARE(obj.value(QLatin1StringView("arrivalTime")).toString(),
0073                  QLatin1String("2018-03-18T19:44:00Z"));
0074         auto dtObj = obj.value(QLatin1StringView("departureTime")).toObject();
0075         QCOMPARE(dtObj.value(QLatin1StringView("@value")).toString(),
0076                  QLatin1String("2018-03-18T18:44:00+01:00"));
0077         QCOMPARE(dtObj.value(QLatin1StringView("@type")).toString(),
0078                  QLatin1String("QDateTime"));
0079         QCOMPARE(dtObj.value(QLatin1StringView("timezone")).toString(),
0080                  QLatin1String("Europe/Berlin"));
0081         QCOMPARE(obj.value(QLatin1StringView("departureDay")).toString(),
0082                  QLatin1String("2018-03-18"));
0083 
0084         auto obj2 = obj.value(QLatin1StringView("departureAirport")).toObject();
0085         QCOMPARE(obj2.value(QLatin1StringView("@type")).toString(),
0086                  QLatin1String("Airport"));
0087 
0088         QVERIFY(obj.contains(QLatin1StringView("departureGate")));
0089         QCOMPARE(obj.value(QLatin1StringView("departureGate")).toString(),
0090                  QLatin1String(""));
0091 
0092         QVERIFY(obj.contains(QLatin1StringView("airline")));
0093 
0094         qDebug().noquote() << QJsonDocument(obj).toJson();
0095 
0096         // integer values
0097         FoodEstablishmentReservation res;
0098         res.setPartySize(2);
0099         const QString reservationNumber{QStringLiteral("OT123456")};
0100         res.setReservationNumber(reservationNumber);
0101         res.setStartTime(QDateTime(QDate(2018, 3, 18), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0102         Person person;
0103         const QString fullName{QStringLiteral("John")};
0104 
0105         person.setName(fullName);
0106         res.setUnderName(person);
0107 
0108         array = JsonLdDocument::toJson(QList<QVariant>({res}));
0109         QCOMPARE(array.size(), 1);
0110         obj = array.at(0).toObject();
0111         QCOMPARE(obj.value(QLatin1StringView("partySize")).toInt(), 2);
0112         QCOMPARE(obj.value(QLatin1StringView("reservationNumber")).toString(),
0113                  reservationNumber);
0114         auto resDtObj = obj.value(QLatin1StringView("startTime")).toObject();
0115         QCOMPARE(resDtObj.value(QLatin1StringView("@value")).toString(),
0116                  QLatin1String("2018-03-18T18:44:00+01:00"));
0117         QCOMPARE(resDtObj.value(QLatin1StringView("@type")).toString(),
0118                  QLatin1String("QDateTime"));
0119         QCOMPARE(resDtObj.value(QLatin1StringView("timezone")).toString(),
0120                  QLatin1String("Europe/Berlin"));
0121         qDebug().noquote() << QJsonDocument(obj).toJson();
0122         auto undernameObj =
0123             obj.value(QLatin1StringView("underName")).toObject();
0124         QCOMPARE(undernameObj.value(QLatin1StringView("name")).toString(),
0125                  QLatin1String("John"));
0126 
0127         //Rental Car
0128         RentalCarReservation rentalRes;
0129         const QString reservationRentalNumber{QStringLiteral("OT1234567")};
0130         rentalRes.setReservationNumber(reservationRentalNumber);
0131         Person personRentalCal;
0132         const QString fullNameRentalCar{QStringLiteral("John2")};
0133 
0134         personRentalCal.setName(fullNameRentalCar);
0135         rentalRes.setUnderName(personRentalCal);
0136         rentalRes.setPickupTime(QDateTime(QDate(2018, 3, 18), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0137         rentalRes.setDropoffTime(QDateTime(QDate(2018, 3, 21), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0138 
0139         Place placeDropLocation;
0140         placeDropLocation.setName(QStringLiteral("droplocation"));
0141         KItinerary::PostalAddress placeDropPostalAddress;
0142         placeDropPostalAddress.setStreetAddress(QStringLiteral("8 foo bla bla"));
0143         placeDropPostalAddress.setAddressLocality(QStringLiteral("bli"));
0144         placeDropLocation.setAddress(placeDropPostalAddress);
0145 
0146         rentalRes.setDropoffLocation(placeDropLocation);
0147 
0148         Place placePickupLocation;
0149         placePickupLocation.setName(QStringLiteral("pickuplocation"));
0150         KItinerary::PostalAddress placePickupPostalAddress;
0151         placePickupPostalAddress.setStreetAddress(QStringLiteral("5 kde foo bla bla"));
0152         placePickupPostalAddress.setAddressLocality(QStringLiteral("bli2"));
0153         placePickupLocation.setAddress(placePickupPostalAddress);
0154 
0155         rentalRes.setPickupLocation(placePickupLocation);
0156 
0157         obj = JsonLdDocument::toJson(rentalRes);
0158         QCOMPARE(obj.value(QLatin1StringView("reservationNumber")).toString(),
0159                  reservationRentalNumber);
0160 
0161         qDebug().noquote() << QJsonDocument(obj).toJson();
0162         undernameObj = obj.value(QLatin1StringView("underName")).toObject();
0163         QCOMPARE(undernameObj.value(QLatin1StringView("name")).toString(),
0164                  fullNameRentalCar);
0165 
0166         auto pickupTimeObj =
0167             obj.value(QLatin1StringView("dropoffTime")).toObject();
0168         QCOMPARE(pickupTimeObj.value(QLatin1StringView("@value")).toString(),
0169                  QLatin1String("2018-03-21T18:44:00+01:00"));
0170         QCOMPARE(pickupTimeObj.value(QLatin1StringView("@type")).toString(),
0171                  QLatin1String("QDateTime"));
0172         QCOMPARE(pickupTimeObj.value(QLatin1StringView("timezone")).toString(),
0173                  QLatin1String("Europe/Berlin"));
0174 
0175         auto droptimeObj =
0176             obj.value(QLatin1StringView("pickupTime")).toObject();
0177         QCOMPARE(droptimeObj.value(QLatin1StringView("@value")).toString(),
0178                  QLatin1String("2018-03-18T18:44:00+01:00"));
0179         QCOMPARE(droptimeObj.value(QLatin1StringView("@type")).toString(),
0180                  QLatin1String("QDateTime"));
0181         QCOMPARE(droptimeObj.value(QLatin1StringView("timezone")).toString(),
0182                  QLatin1String("Europe/Berlin"));
0183     }
0184 
0185     void testDeserialization()
0186     {
0187         QByteArray b("[{"
0188             "\"@context\": \"http://schema.org\","
0189             "\"@type\": \"Flight\","
0190             "\"departureAirport\": {"
0191                 "\"@type\": \"Airport\","
0192                 "\"iataCode\": \"TXL\","
0193                 "\"name\": \"Berlin Tegel\""
0194             "},"
0195             "\"departureTime\": \"2018-03-18T18:44:00+01:00\","
0196             "\"departureDay\": \"2018-03-17\","
0197             "\"arrivalTime\": { \"@type\": \"QDateTime\", \"@value\": \"2018-03-18T19:44:00+01:00\", \"timezone\": \"Europe/Berlin\" },"
0198             "\"departureGate\": \"\","
0199             "\"flightNumber\": \"1234\""
0200         "}]");
0201 
0202         auto array = QJsonDocument::fromJson(b).array();
0203         auto datas = JsonLdDocument::fromJson(array);
0204         QCOMPARE(datas.size(), 1);
0205 
0206         auto data = datas.at(0);
0207         QVERIFY(data.canConvert<Flight>());
0208         auto flight = data.value<Flight>();
0209         QCOMPARE(flight.flightNumber(), QLatin1StringView("1234"));
0210         QCOMPARE(flight.departureAirport().iataCode(),
0211                  QLatin1StringView("TXL"));
0212         QCOMPARE(flight.departureAirport().name(),
0213                  QLatin1StringView("Berlin Tegel"));
0214         QCOMPARE(flight.departureTime(), QDateTime(QDate(2018, 3, 18), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0215         QCOMPARE(flight.departureDay(), QDate(2018, 3, 17));
0216         QCOMPARE(flight.arrivalTime(), QDateTime(QDate(2018, 3, 18), QTime(19, 44, 0), QTimeZone("Europe/Berlin")));
0217         QCOMPARE(flight.arrivalTime().timeSpec(), Qt::TimeZone);
0218         QCOMPARE(flight.arrivalTime().timeZone(), QTimeZone("Europe/Berlin"));
0219 
0220         QVERIFY(flight.departureGate().isEmpty());
0221         QVERIFY(!flight.departureGate().isNull());
0222 
0223         // integer values
0224         b = QByteArray("[{"
0225             "\"@context\": \"http://schema.org\","
0226             "\"@type\": \"FoodEstablishmentReservation\","
0227             "\"partySize\": 42,"
0228             "\"reservationNumber\": \"0T44542\","
0229             "\"underName\": {"
0230             "    \"@type\": \"Person\","
0231             "    \"name\": \"John Smith\","
0232             "    \"email\": \"foo@kde.org\""
0233             "},"
0234             "\"reservationFor\": {"
0235             "     \"@type\": \"FoodEstablishment\","
0236             "     \"name\": \"Wagamama\","
0237             "     \"address\": {"
0238             "           \"@type\": \"PostalAddress\","
0239             "           \"streetAddress\": \"1 Tavistock Street\","
0240             "           \"addressLocality\": \"London\","
0241             "           \"addressRegion\": \"Greater London\","
0242             "           \"postalCode\": \"WC2E 7PG\","
0243             "           \"addressCountry\": \"United Kingdom\""
0244             "     }"
0245             "}"
0246         "}]");
0247 
0248         array = QJsonDocument::fromJson(b).array();
0249         datas = JsonLdDocument::fromJson(array);
0250         QCOMPARE(datas.size(), 1);
0251         data = datas.at(0);
0252         QVERIFY(data.canConvert<FoodEstablishmentReservation>());
0253         auto res = data.value<FoodEstablishmentReservation>();
0254         QCOMPARE(res.partySize(), 42);
0255         QCOMPARE(res.reservationNumber(), QStringLiteral("0T44542"));
0256         QCOMPARE(res.underName().value<Person>().name(), QStringLiteral("John Smith"));
0257         QCOMPARE(res.underName().value<Person>().email(), QStringLiteral("foo@kde.org"));
0258 
0259         const auto foodEstablishment = res.reservationFor().value<FoodEstablishment>();
0260         const auto address = foodEstablishment.address();
0261         QCOMPARE(address.addressCountry(), QStringLiteral("United Kingdom"));
0262         QCOMPARE(address.addressLocality(), QStringLiteral("London"));
0263         QCOMPARE(address.postalCode(), QStringLiteral("WC2E 7PG"));
0264         QCOMPARE(address.streetAddress(), QStringLiteral("1 Tavistock Street"));
0265         QCOMPARE(address.addressRegion(), QStringLiteral("Greater London"));
0266 
0267         //RentalCar
0268         b = QByteArray("[{"
0269             "\"@context\": \"http://schema.org\","
0270             "\"@type\": \"RentalCarReservation\","
0271             "\"reservationNumber\": \"0T445424\","
0272             "\"underName\": {"
0273             "    \"@type\": \"Person\","
0274             "    \"name\": \"John Smith\","
0275             "    \"email\": \"foo@kde.org\""
0276             "},"
0277             "\"pickupLocation\": {"
0278             "    \"@type\": \"Place\","
0279             "    \"address\": {"
0280             "       \"@type\": \"PostalAddress\","
0281             "       \"addressLocality\": \"bli2\","
0282             "       \"streetAddress\": \"5 kde foo bla bla\""
0283             "},"
0284             "\"name\": \"pickuplocation\""
0285             "},"
0286             "\"dropoffLocation\": {"
0287             "    \"@type\": \"Place\","
0288             "    \"address\": {"
0289             "       \"@type\": \"PostalAddress\","
0290             "       \"addressLocality\": \"bli3\","
0291             "       \"streetAddress\": \"7 kde foo bla bla\""
0292             "},"
0293             "\"name\": \"droplocation\""
0294             "},"
0295             "\"reservationFor\": {"
0296             "    \"@type\": \"RentalCar\","
0297             "    \"name\": \"Economy Class Car\","
0298             "    \"model\": \"Civic\","
0299             "    \"brand\": {"
0300             "       \"@type\": \"Brand\","
0301             "       \"name\": \"Honda\""
0302             "    },"
0303             "    \"rentalCompany\": {"
0304             "          \"@type\": \"Organization\","
0305             "          \"name\": \"Hertz\""
0306             "    }"
0307             "},"
0308             "\"pickupTime\": \"2018-03-18T18:44:00+01:00\","
0309             "\"dropoffTime\": \"2018-03-21T18:44:00+01:00\""
0310         "}]");
0311 
0312         array = QJsonDocument::fromJson(b).array();
0313         datas = JsonLdDocument::fromJson(array);
0314         QCOMPARE(datas.size(), 1);
0315         data = datas.at(0);
0316         QVERIFY(data.canConvert<RentalCarReservation>());
0317         auto resRentCar = data.value<RentalCarReservation>();
0318         QCOMPARE(resRentCar.reservationNumber(), QStringLiteral("0T445424"));
0319         QCOMPARE(resRentCar.underName().value<Person>().name(), QStringLiteral("John Smith"));
0320         QCOMPARE(resRentCar.underName().value<Person>().email(), QStringLiteral("foo@kde.org"));
0321         QCOMPARE(resRentCar.pickupTime(), QDateTime(QDate(2018, 3, 18), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0322         QCOMPARE(resRentCar.dropoffTime(), QDateTime(QDate(2018, 3, 21), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0323         const auto dropoffLocation = resRentCar.dropoffLocation();
0324         QCOMPARE(dropoffLocation.name(), QStringLiteral("droplocation"));
0325         const auto dropOffLocationAddress = dropoffLocation.address();
0326         QCOMPARE(dropOffLocationAddress.streetAddress(), QStringLiteral("7 kde foo bla bla"));
0327         QCOMPARE(dropOffLocationAddress.addressLocality(), QStringLiteral("bli3"));
0328 
0329         const auto pickupLocation = resRentCar.pickupLocation();
0330         QCOMPARE(pickupLocation.name(), QStringLiteral("pickuplocation"));
0331         const auto pickupLocationAddress = pickupLocation.address();
0332         QCOMPARE(pickupLocationAddress.streetAddress(), QStringLiteral("5 kde foo bla bla"));
0333         QCOMPARE(pickupLocationAddress.addressLocality(), QStringLiteral("bli2"));
0334 
0335         const auto reservationForRentalCar = resRentCar.reservationFor().value<RentalCar>();
0336         QCOMPARE(reservationForRentalCar.name(), QStringLiteral("Economy Class Car"));
0337         QCOMPARE(reservationForRentalCar.model(), QStringLiteral("Civic"));
0338         const auto brand = reservationForRentalCar.brand();
0339         QCOMPARE(brand.name(), QStringLiteral("Honda"));
0340 
0341         const auto rentalCarOrganization = reservationForRentalCar.rentalCompany();
0342         QCOMPARE(rentalCarOrganization.name(), QStringLiteral("Hertz"));
0343 
0344         //Taxi Reservation
0345         b = QByteArray("[{"
0346             "\"@context\": \"http://schema.org\","
0347             "\"@type\": \"TaxiReservation\","
0348             "\"reservationId\": \"0T445424\","
0349             "\"underName\": {"
0350             "    \"@type\": \"Person\","
0351             "    \"name\": \"John Smith2\","
0352             "    \"email\": \"foo@kde.org\""
0353             "},"
0354             "\"pickupLocation\": {"
0355             "    \"@type\": \"Place\","
0356             "    \"address\": {"
0357             "       \"@type\": \"PostalAddress\","
0358             "       \"addressLocality\": \"bli2\","
0359             "       \"streetAddress\": \"5 kde foo bla bla\""
0360             "     }"
0361             "},"
0362             "\"reservationFor\": {"
0363             "    \"@type\": \"Taxi\","
0364             "    \"provider\": {"
0365             "       \"@type\": \"Organization\","
0366             "       \"name\": \"Checker Cab\""
0367             "    }"
0368             "},"
0369             "\"pickupTime\": \"2018-03-18T18:44:00+01:00\""
0370         "}]");
0371         array = QJsonDocument::fromJson(b).array();
0372         datas = JsonLdDocument::fromJson(array);
0373         QCOMPARE(datas.size(), 1);
0374         data = datas.at(0);
0375         QVERIFY(data.canConvert<TaxiReservation>());
0376         auto resTaxi = data.value<TaxiReservation>();
0377         QCOMPARE(resTaxi.reservationNumber(), QStringLiteral("0T445424"));
0378         QCOMPARE(resTaxi.underName().value<Person>().name(), QStringLiteral("John Smith2"));
0379         QCOMPARE(resTaxi.underName().value<Person>().email(), QStringLiteral("foo@kde.org"));
0380 
0381         const auto pickUpLocationTaxi = resTaxi.pickupLocation();
0382         const auto pickupLocationAddressTaxi = pickUpLocationTaxi.address();
0383         QCOMPARE(pickupLocationAddressTaxi.streetAddress(), QStringLiteral("5 kde foo bla bla"));
0384         QCOMPARE(pickupLocationAddressTaxi.addressLocality(), QStringLiteral("bli2"));
0385 
0386         QCOMPARE(resTaxi.pickupTime(), QDateTime(QDate(2018, 3, 18), QTime(18, 44, 0), QTimeZone("Europe/Berlin")));
0387         QVERIFY(resTaxi.reservationFor().canConvert<Taxi>());
0388     }
0389 
0390     void testApply()
0391     {
0392         Flight f1;
0393         f1.setDepartureGate(QStringLiteral("38"));
0394         Airline a1;
0395         a1.setIataCode(QStringLiteral("AB"));
0396         f1.setAirline(a1);
0397 
0398         Flight f2;
0399         f2.setDepartureTerminal(QStringLiteral("A"));
0400         Airline a2;
0401         a2.setName(QStringLiteral("Air Berlin"));
0402         f2.setAirline(a2);
0403 
0404         f1 = JsonLdDocument::apply(f1, f2).value<Flight>();
0405         QCOMPARE(f1.departureGate(), QLatin1StringView("38"));
0406         QCOMPARE(f1.departureTerminal(), QLatin1StringView("A"));
0407         QCOMPARE(f1.airline().iataCode(), QLatin1StringView("AB"));
0408         QCOMPARE(f1.airline().name(), QLatin1StringView("Air Berlin"));
0409     }
0410 
0411     void testDateTimeParsing_data()
0412     {
0413         QTest::addColumn<QByteArray>("dtStr");
0414         QTest::addColumn<QDateTime>("result");
0415 
0416         QTest::newRow("iso") << QByteArray("2018-08-15T22:00:00+02:00") << QDateTime({2018, 8, 15}, {22 ,00}, QTimeZone::fromSecondsAheadOfUtc(7200));
0417         QTest::newRow("weird LH format") << QByteArray("20200826T200000Z") << QDateTime({2020, 8, 26}, {20 ,00}, QTimeZone::UTC);
0418     }
0419 
0420     void testDateTimeParsing()
0421     {
0422         QFETCH(QByteArray, dtStr);
0423         QFETCH(QDateTime, result);
0424 
0425         const auto b = QByteArray("[{"
0426             "\"@context\": \"http://schema.org\","
0427             "\"@type\": \"Flight\","
0428             "\"departureTime\": \"" + dtStr + "\""
0429         "}]");
0430         const auto array = QJsonDocument::fromJson(b).array();
0431         const auto data = JsonLdDocument::fromJson(array);
0432         QCOMPARE(data.size(), 1);
0433         const auto flight = data[0].value<Flight>();
0434         QCOMPARE(flight.departureTime(), result);
0435         QCOMPARE(flight.departureTime().timeSpec(), result.timeSpec());
0436     }
0437 
0438     void testNormalize_data()
0439     {
0440         QTest::addColumn<QString>("inFile");
0441         QTest::addColumn<QString>("refFile");
0442 
0443         QDir dir(QStringLiteral(SOURCE_DIR "/jsonlddata"));
0444         const auto lst = dir.entryList(QStringList(QStringLiteral("*.in.json")), QDir::Files | QDir::Readable | QDir::NoSymLinks);
0445         for (const auto &file : lst) {
0446             const QString refFile = dir.path() + QLatin1Char('/') + file.left(file.size() - 7) + QStringLiteral("out.json");
0447             if (!QFile::exists(refFile)) {
0448                 qDebug() << "reference file" << refFile << "does not exist, skipping test file" << file;
0449                 continue;
0450             }
0451             QTest::newRow(file.toLatin1().constData()) << QString(dir.path() + QLatin1Char('/') +  file) << refFile;
0452         }
0453     }
0454 
0455     void testNormalize()
0456     {
0457         QFETCH(QString, inFile);
0458         QFETCH(QString, refFile);
0459 
0460         const auto inJson = QJsonDocument::fromJson(readFile(inFile)).array();
0461         QVERIFY(!inJson.isEmpty());
0462         const auto normalizedJson = JsonLdDocument::toJson(JsonLdDocument::fromJson(inJson));
0463         QVERIFY(!normalizedJson.isEmpty());
0464         const auto refJson = QJsonDocument::fromJson(readFile(refFile)).array();
0465         QVERIFY(!refJson.isEmpty());
0466 
0467         qDebug() << normalizedJson;
0468         if (normalizedJson != refJson) {
0469           QFile f(refFile + QLatin1StringView(".fail"));
0470           QVERIFY(f.open(QFile::WriteOnly));
0471           f.write(QJsonDocument(normalizedJson).toJson());
0472           f.close();
0473 
0474           QProcess proc;
0475           proc.setProcessChannelMode(QProcess::ForwardedChannels);
0476           proc.start(QStringLiteral("diff"),
0477                      {QStringLiteral("-u"), refFile, f.fileName()});
0478           QVERIFY(proc.waitForFinished());
0479         }
0480         QCOMPARE(normalizedJson, refJson);
0481     }
0482 };
0483 
0484 QTEST_APPLESS_MAIN(JsonLdDocumentTest)
0485 
0486 #include "jsonlddocumenttest.moc"