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

0001 /*
0002     SPDX-FileCopyrightText: 2021 Volker Krause <vkrause@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include <QFile>
0008 #include <QTest>
0009 
0010 #include <KHealthCertificateParser>
0011 #include <KRecoveryCertificate>
0012 #include <KTestCertificate>
0013 #include <KVaccinationCertificate>
0014 
0015 void initLocale()
0016 {
0017     qputenv("LC_ALL", "en_US.utf-8");
0018     qputenv("TZ", "UTC");
0019 }
0020 
0021 Q_CONSTRUCTOR_FUNCTION(initLocale)
0022 
0023 class EuDgcParserTest : public QObject
0024 {
0025     Q_OBJECT
0026 private:
0027     QByteArray readFile(QStringView fileName) const
0028     {
0029         QFile f(QLatin1String(SOURCE_DIR "/data/") + fileName);
0030         if (!f.open(QFile::ReadOnly)) {
0031             qCritical() << f.errorString() << f.fileName();
0032         }
0033         return f.readAll();
0034     }
0035 
0036 private Q_SLOTS:
0037     void testVaccinationCertificate()
0038     {
0039         auto cert = KHealthCertificateParser::parse(readFile(u"eu-dgc/full-vaccination.txt"));
0040         QCOMPARE(cert.userType(), qMetaTypeId<KVaccinationCertificate>());
0041         auto vac = cert.value<KVaccinationCertificate>();
0042         QCOMPARE(vac.name(), QLatin1String("Erika Mustermann"));
0043         QCOMPARE(vac.disease(), QLatin1String("COVID-19"));
0044         QCOMPARE(vac.dateOfBirth(), QDate(1964, 8, 12));
0045         QCOMPARE(vac.country(), QLatin1String("DE"));
0046         QCOMPARE(vac.dose(), 2);
0047         QCOMPARE(vac.totalDoses(), 2);
0048         QCOMPARE(vac.date(), QDate(2021, 5, 29));
0049         QCOMPARE(vac.vaccineType(), QLatin1String("SARS-CoV-2 mRNA vaccine"));
0050         QCOMPARE(vac.vaccine(), QLatin1String("Spikevax"));
0051         QCOMPARE(vac.vaccineUrl().toString(), QLatin1String("https://ec.europa.eu/health/documents/community-register/html/h1507.htm"));
0052         QCOMPARE(vac.manufacturer(), QLatin1String("Moderna Biotech Spain S.L."));
0053         QCOMPARE(vac.certificateIssuer(), QLatin1String("Robert Koch-Institut"));
0054         QCOMPARE(vac.certificateId(), QLatin1String("URN:UVCI:01DE/IZ12345A/5CWLU12RNOB9RXSEOP6FG8#W"));
0055         QCOMPARE(vac.certificateIssueDate(), QDateTime({2021, 5, 29}, {19, 21, 13}));
0056         QCOMPARE(vac.certificateExpiryDate(), QDateTime({2022, 1, 28}, {7, 47, 53}));
0057         QCOMPARE(vac.signatureState(), KHealthCertificate::ValidSignature);
0058         QCOMPARE(vac.validationState(), KHealthCertificate::Invalid); // expired by now
0059         QCOMPARE(vac.vaccinationState(), KVaccinationCertificate::Invalid); // expired by now
0060         QCOMPARE(vac.rawData(), readFile(u"eu-dgc/full-vaccination.txt"));
0061         QCOMPARE(KHealthCertificate::relevantUntil(vac), QDateTime({2022, 1, 28}, {7, 47, 53}));
0062 
0063         cert = KHealthCertificateParser::parse(readFile(u"eu-dgc/partial-vaccination.txt"));
0064         QCOMPARE(cert.userType(), qMetaTypeId<KVaccinationCertificate>());
0065         vac = cert.value<KVaccinationCertificate>();
0066         QCOMPARE(vac.name(), QLatin1String("Erika Mustermann"));
0067         QCOMPARE(vac.disease(), QLatin1String("COVID-19"));
0068         QCOMPARE(vac.dateOfBirth(), QDate(1964, 8, 12));
0069         QCOMPARE(vac.country(), QLatin1String("DE"));
0070         QCOMPARE(vac.dose(), 1);
0071         QCOMPARE(vac.totalDoses(), 2);
0072         QCOMPARE(vac.date(), QDate(2021, 5, 29));
0073         QCOMPARE(vac.vaccineType(), QLatin1String("SARS-CoV-2 mRNA vaccine"));
0074         QCOMPARE(vac.vaccine(), QLatin1String("Spikevax"));
0075         QCOMPARE(vac.manufacturer(), QLatin1String("Moderna Biotech Spain S.L."));
0076         QCOMPARE(vac.certificateIssuer(), QLatin1String("Robert Koch-Institut"));
0077         QCOMPARE(vac.certificateId(), QLatin1String("URN:UVCI:01DE/IZ12345A/5CWLU12RNOB9RXSEOP6FG8#W"));
0078         QCOMPARE(vac.certificateIssueDate(), QDateTime({2021, 5, 29}, {19, 21, 13}));
0079         QCOMPARE(vac.certificateExpiryDate(), QDateTime({2022, 1, 28}, {7, 47, 53}));
0080         QCOMPARE(vac.signatureState(), KHealthCertificate::ValidSignature);
0081         QCOMPARE(vac.validationState(), KHealthCertificate::Invalid); // expired by now
0082         QCOMPARE(vac.vaccinationState(), KVaccinationCertificate::Invalid); // expired by now
0083         QCOMPARE(vac.rawData(), readFile(u"eu-dgc/partial-vaccination.txt"));
0084 
0085         // Swiss certificates use another signature algorithm
0086         cert = KHealthCertificateParser::parse(readFile(u"eu-dgc/full-vaccination-ch.txt"));
0087         QCOMPARE(cert.userType(), qMetaTypeId<KVaccinationCertificate>());
0088         vac = cert.value<KVaccinationCertificate>();
0089         QCOMPARE(vac.name(), QLatin1String("Martina Studer"));
0090         QCOMPARE(vac.country(), QLatin1String("CH"));
0091         QCOMPARE(vac.signatureState(), KHealthCertificate::ValidSignature);
0092         QCOMPARE(vac.certificateExpiryDate(), QDateTime({2023, 6, 28}, {16, 22, 25}));
0093         // QCOMPARE(vac.validationState(), KHealthCertificate::Valid);
0094         // QCOMPARE(vac.vaccinationState(), KVaccinationCertificate::FullyVaccinated);
0095         QCOMPARE(vac.rawData(), readFile(u"eu-dgc/full-vaccination-ch.txt"));
0096     }
0097 
0098     void testTestCertificates()
0099     {
0100         auto cert = KHealthCertificateParser::parse(readFile(u"eu-dgc/negative-test.txt"));
0101         QCOMPARE(cert.userType(), qMetaTypeId<KTestCertificate>());
0102         auto test = cert.value<KTestCertificate>();
0103         QCOMPARE(test.name(), QLatin1String("Erika Mustermann"));
0104         QCOMPARE(test.disease(), QLatin1String("COVID-19"));
0105         QCOMPARE(test.dateOfBirth(), QDate(1964, 8, 12));
0106         QCOMPARE(test.country(), QLatin1String("DE"));
0107         QCOMPARE(test.date(), QDate(2021, 5, 30));
0108         QCOMPARE(test.testType(), QLatin1String("Rapid immunoassay"));
0109         QCOMPARE(test.result(), KTestCertificate::Negative);
0110         QCOMPARE(test.resultString(), QLatin1String("Not detected"));
0111         QCOMPARE(test.certificateIssuer(), QLatin1String("Robert Koch-Institut"));
0112         QCOMPARE(test.certificateId(), QLatin1String("URN:UVCI:01DE/IZ12345A/5CWLU12RNOB9RXSEOP6FG8#W"));
0113         QCOMPARE(test.certificateIssueDate(), QDateTime({2021, 5, 29}, {19, 21, 13}));
0114         QCOMPARE(test.certificateExpiryDate(), QDateTime({2022, 1, 28}, {7, 47, 53}));
0115         QCOMPARE(test.signatureState(), KHealthCertificate::ValidSignature);
0116         QCOMPARE(test.validationState(), KHealthCertificate::Invalid); // expired
0117         QCOMPARE(test.isCurrent(), false);
0118         QCOMPARE(test.rawData(), readFile(u"eu-dgc/negative-test.txt"));
0119         QCOMPARE(KHealthCertificate::relevantUntil(test), QDateTime({2021, 6, 1}, {}));
0120 
0121         cert = KHealthCertificateParser::parse(readFile(u"eu-dgc/negative-rat-test-cz.txt"));
0122         QCOMPARE(cert.userType(), qMetaTypeId<KTestCertificate>());
0123         test = cert.value<KTestCertificate>();
0124         QCOMPARE(test.name(), QStringLiteral("Jan Novák"));
0125         QCOMPARE(test.disease(), QLatin1String("COVID-19"));
0126         QCOMPARE(test.country(), QLatin1String("CZ"));
0127         QCOMPARE(test.testType(), QLatin1String("Rapid immunoassay"));
0128         QVERIFY(!test.testName().isEmpty());
0129         QCOMPARE(test.testUrl().toString(), QLatin1String("https://covid-19-diagnostics.jrc.ec.europa.eu/devices/detail/1242"));
0130         QCOMPARE(test.result(), KTestCertificate::Negative);
0131         QCOMPARE(test.signatureState(), KHealthCertificate::ValidSignature);
0132         QCOMPARE(test.isCurrent(), false);
0133     }
0134 
0135     void testRecoveryCertificates()
0136     {
0137         auto cert = KHealthCertificateParser::parse(readFile(u"eu-dgc/recovery.txt"));
0138         QCOMPARE(cert.userType(), qMetaTypeId<KRecoveryCertificate>());
0139         auto test = cert.value<KRecoveryCertificate>();
0140         QCOMPARE(test.name(), QLatin1String("Erika Mustermann"));
0141         QCOMPARE(test.disease(), QLatin1String("COVID-19"));
0142         QCOMPARE(test.dateOfBirth(), QDate(1964, 8, 12));
0143         QCOMPARE(test.dateOfPositiveTest(), QDate(2021, 1, 10));
0144         QCOMPARE(test.validFrom(), QDate(2021, 5, 29));
0145         QCOMPARE(test.validUntil(), QDate(2021, 6, 15));
0146         QCOMPARE(test.certificateIssuer(), QLatin1String("Robert Koch-Institut"));
0147         QCOMPARE(test.certificateId(), QLatin1String("URN:UVCI:01DE/5CWLU12RNOB9RXSEOP6FG8#W"));
0148         QCOMPARE(test.certificateIssueDate(), QDateTime({2021, 5, 29}, {19, 21, 13}));
0149         QCOMPARE(test.certificateExpiryDate(), QDateTime({2022, 1, 28}, {7, 47, 53}));
0150         QCOMPARE(test.signatureState(), KHealthCertificate::ValidSignature);
0151         QCOMPARE(test.validationState(), KHealthCertificate::Invalid); // expired by now
0152         QCOMPARE(test.rawData(), readFile(u"eu-dgc/recovery.txt"));
0153         QCOMPARE(KHealthCertificate::relevantUntil(test), QDateTime({2021, 6, 15}, {}));
0154     }
0155 };
0156 
0157 QTEST_APPLESS_MAIN(EuDgcParserTest)
0158 
0159 #include "eudgcparsertest.moc"