File indexing completed on 2024-05-12 05:09:58

0001 /***************************************************************************
0002     Copyright (C) 2009-2023 Robby Stephenson <robby@periapsis.org>
0003  ***************************************************************************/
0004 
0005 /***************************************************************************
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or         *
0008  *   modify it under the terms of the GNU General Public License as        *
0009  *   published by the Free Software Foundation; either version 2 of        *
0010  *   the License or (at your option) version 3 or any later version        *
0011  *   accepted by the membership of KDE e.V. (or its successor approved     *
0012  *   by the membership of KDE e.V.), which shall act as a proxy            *
0013  *   defined in Section 14 of version 3 of the license.                    *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #include "entrycomparisontest.h"
0026 
0027 #include "../collection.h"
0028 #include "../field.h"
0029 #include "../entry.h"
0030 #include "../collections/bookcollection.h"
0031 #include "../collections/bibtexcollection.h"
0032 #include "../collections/videocollection.h"
0033 #include "../collections/comicbookcollection.h"
0034 #include "../collections/musiccollection.h"
0035 #include "../collections/gamecollection.h"
0036 #include "../collections/filecatalog.h"
0037 #include "../entrycomparison.h"
0038 
0039 #include <KLocalizedString>
0040 
0041 #include <QTest>
0042 #include <QLoggingCategory>
0043 #include <QStandardPaths>
0044 
0045 QTEST_GUILESS_MAIN( EntryComparisonTest )
0046 
0047 Q_DECLARE_METATYPE(Tellico::EntryComparison::MatchValue)
0048 
0049 void EntryComparisonTest::initTestCase() {
0050   QStandardPaths::setTestModeEnabled(true);
0051   QLoggingCategory::setFilterRules(QStringLiteral("tellico.debug = true\ntellico.info = false"));
0052   qRegisterMetaType<Tellico::EntryComparison::MatchValue>();
0053   KLocalizedString::setApplicationDomain("tellico");
0054 //  Tellico::ImageFactory::init();
0055 
0056   // create the collection and entry used for testMatchScore()
0057   m_coll = Tellico::Data::CollPtr(new Tellico::Data::BookCollection(true));
0058   m_entry = Tellico::Data::EntryPtr(new Tellico::Data::Entry(m_coll));
0059   m_entry->setField(QStringLiteral("title"), QStringLiteral("title1"));
0060   m_entry->setField(QStringLiteral("author"), QStringLiteral("John Doe"));
0061   m_entry->setField(QStringLiteral("isbn"), QStringLiteral("1234367890"));
0062   m_entry->setField(QStringLiteral("lccn"), QStringLiteral("89456"));
0063   Tellico::Data::FieldPtr f(new Tellico::Data::Field(QStringLiteral("arxiv"), QStringLiteral("Arxiv ID")));
0064   m_coll->addField(f);
0065   m_entry->setField(QStringLiteral("arxiv"), QStringLiteral("hep-lat/0110180"));
0066   m_coll->addEntries(m_entry);
0067 }
0068 
0069 void EntryComparisonTest::cleanupTestCase() {
0070 //  Tellico::ImageFactory::clean(true);
0071 }
0072 
0073 void EntryComparisonTest::testMatchScore() {
0074   QFETCH(QString, field);
0075   QFETCH(QString, value);
0076   QFETCH(Tellico::EntryComparison::MatchValue, score);
0077 
0078   QVERIFY(m_coll);
0079   Tellico::Data::EntryPtr e(new Tellico::Data::Entry(m_coll));
0080   e->setField(field, value);
0081   QCOMPARE(Tellico::EntryComparison::score(m_entry, e, field, m_coll.data()), int(score));
0082 }
0083 
0084 void EntryComparisonTest::testMatchScore_data() {
0085   QTest::addColumn<QString>("field");
0086   QTest::addColumn<QString>("value");
0087   QTest::addColumn<Tellico::EntryComparison::MatchValue>("score");
0088 
0089   QTest::newRow("empty title") << QStringLiteral("title") << QString() << Tellico::EntryComparison::MATCH_VALUE_NONE;
0090   QTest::newRow("title match") << QStringLiteral("title") << QStringLiteral("title1") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0091   QTest::newRow("title match case") << QStringLiteral("title") << QStringLiteral("TITLE1") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0092 //  QTest::newRow("title match articles") << QStringLiteral("title") << QStringLiteral("THE TITLE1") << Tellico::EntryComparison::MATCH_VALUE_WEAK;
0093   QTest::newRow("title match non alphanum") << QStringLiteral("title") << QStringLiteral("title1.") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0094 //  QTest::newRow("title match paren") << QStringLiteral("title") << QStringLiteral("title1 (old)") << Tellico::EntryComparison::MATCH_VALUE_WEAK;
0095   QTest::newRow("isbn match") << QStringLiteral("isbn") << QStringLiteral("1234367890") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0096   QTest::newRow("isbn match formatted") << QStringLiteral("isbn") << QStringLiteral("1-234-36789-0") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0097   QTest::newRow("lccn match") << QStringLiteral("lccn") << QStringLiteral("89456") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0098   QTest::newRow("lccn match formatted") << QStringLiteral("lccn") << QStringLiteral("89-456") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0099   QTest::newRow("arxiv") << QStringLiteral("arxiv") << QStringLiteral("hep-lat/0110180") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0100   QTest::newRow("arxiv format1") << QStringLiteral("arxiv") << QStringLiteral("hep-lat/0110180v1") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0101   QTest::newRow("arxiv format2") << QStringLiteral("arxiv") << QStringLiteral("arxiv:hep-lat/0110180v1") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0102   QTest::newRow("author") << QStringLiteral("author") << QStringLiteral("John Doe") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0103   QTest::newRow("author formatted") << QStringLiteral("author") << QStringLiteral("Doe, John") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0104   QTest::newRow("author formatted2") << QStringLiteral("author") << QStringLiteral("doe, john") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0105   QTest::newRow("author multiple") << QStringLiteral("author") << QStringLiteral("John Doe; Jane Doe") << Tellico::EntryComparison::MATCH_VALUE_STRONG;
0106 }
0107 
0108 void EntryComparisonTest::testBookMatch() {
0109   Tellico::Data::CollPtr c(new Tellico::Data::BookCollection(true));
0110 
0111   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0112   e1->setField(QStringLiteral("title"), QStringLiteral("title1"));
0113   e1->setField(QStringLiteral("author"), QStringLiteral("author1"));
0114   e1->setField(QStringLiteral("edition"), QStringLiteral("edition1"));
0115   e1->setField(QStringLiteral("pur_price"), QStringLiteral("price1"));
0116   e1->setField(QStringLiteral("isbn"), QStringLiteral("1234567890"));
0117   c->addEntries(e1);
0118 
0119   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0120   e2->setField(QStringLiteral("title"), QStringLiteral("title2"));
0121   e2->setField(QStringLiteral("author"), QStringLiteral("author2"));
0122   e2->setField(QStringLiteral("edition"), QStringLiteral("edition2"));
0123   e2->setField(QStringLiteral("pur_price"), QStringLiteral("price2"));
0124   e2->setField(QStringLiteral("isbn"), QStringLiteral("000000000"));
0125 
0126   // not a good match
0127   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0128 
0129   // matching the title makes a good match, even if author does not match
0130   e2->setField(QStringLiteral("title"), QStringLiteral("title1"));
0131   QVERIFY(c->sameEntry(e1, e2) > Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0132 
0133   // title and author both matching are enough for high confidence
0134   e2->setField(QStringLiteral("author"), QStringLiteral("author1"));
0135   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0136 
0137   // perfect match for isbn by itself
0138   e2->setField(QStringLiteral("title"), QString());
0139   e2->setField(QStringLiteral("author"), QString());
0140   e2->setField(QStringLiteral("isbn"), QStringLiteral("1234567890"));
0141   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0142 }
0143 
0144 void EntryComparisonTest::testBibtexMatch() {
0145   Tellico::Data::CollPtr c(new Tellico::Data::BibtexCollection(true));
0146 
0147   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0148   e1->setField(QStringLiteral("title"), QStringLiteral("title1"));
0149   e1->setField(QStringLiteral("author"), QStringLiteral("author1"));
0150   e1->setField(QStringLiteral("edition"), QStringLiteral("edition1"));
0151   e1->setField(QStringLiteral("doi"), QStringLiteral("1234567890"));
0152   c->addEntries(e1);
0153 
0154   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0155   e2->setField(QStringLiteral("title"), QStringLiteral("title2"));
0156   e2->setField(QStringLiteral("author"), QStringLiteral("author2"));
0157   e2->setField(QStringLiteral("edition"), QStringLiteral("edition2"));
0158   e2->setField(QStringLiteral("doi"), QStringLiteral("000000000"));
0159 
0160   // not a good match
0161   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0162 
0163   // matching the title makes a good match, even if author does not match
0164   e2->setField(QStringLiteral("title"), QStringLiteral("title1"));
0165   QVERIFY(c->sameEntry(e1, e2) > Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0166 
0167   // title and author both matching are enough for high confidence
0168   e2->setField(QStringLiteral("author"), QStringLiteral("author1"));
0169   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0170 
0171   // perfect match for doi by itself
0172   e2->setField(QStringLiteral("title"), QString());
0173   e2->setField(QStringLiteral("author"), QString());
0174   e2->setField(QStringLiteral("doi"), QStringLiteral("1234567890"));
0175   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0176 }
0177 
0178 void EntryComparisonTest::testComicMatch() {
0179   Tellico::Data::CollPtr c(new Tellico::Data::ComicBookCollection(true));
0180 
0181   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0182   e1->setField(QStringLiteral("title"), QStringLiteral("title1"));
0183   e1->setField(QStringLiteral("series"), QStringLiteral("series1"));
0184   e1->setField(QStringLiteral("issue"), QStringLiteral("1"));
0185   c->addEntries(e1);
0186 
0187   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0188   e2->setField(QStringLiteral("title"), QStringLiteral("title2"));
0189 
0190   // not a good match
0191   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0192 
0193   // matching the title makes a good match, even if author does not match
0194   e2->setField(QStringLiteral("title"), QStringLiteral("title1"));
0195   QVERIFY(c->sameEntry(e1, e2) > Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0196 
0197   // matching series and issue makes a perfect match
0198   e2->setField(QStringLiteral("series"), QStringLiteral("series1"));
0199   e2->setField(QStringLiteral("issue"), QStringLiteral("1"));
0200   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0201 }
0202 
0203 void EntryComparisonTest::testVideoMatch() {
0204   Tellico::Data::CollPtr c(new Tellico::Data::VideoCollection(true));
0205   Tellico::Data::FieldPtr f(new Tellico::Data::Field(QStringLiteral("imdb"),
0206                                                      QStringLiteral("IMDB"),
0207                                                      Tellico::Data::Field::URL));
0208   c->addField(f);
0209 
0210   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0211   e1->setField(QStringLiteral("title"), QStringLiteral("the man from snowy river"));
0212   e1->setField(QStringLiteral("year"), QStringLiteral("1982"));
0213   e1->setField(QStringLiteral("director"), QStringLiteral("a director"));
0214   e1->setField(QStringLiteral("studio"), QStringLiteral("studio 7"));
0215   c->addEntries(e1);
0216 
0217   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0218   e2->setField(QStringLiteral("title"), QStringLiteral("man from snowy river, the"));
0219 
0220   // not a good match
0221   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0222 
0223   // matching the year makes a good match
0224   e2->setField(QStringLiteral("year"), QStringLiteral("1982"));
0225   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0226 
0227   // matching the title exactly and year makes a perfect match
0228   e2->setField(QStringLiteral("title"), QStringLiteral("the man from snowy river"));
0229   e2->setField(QStringLiteral("year"), QStringLiteral("1982"));
0230   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0231 
0232   // imdb link should be pefect match by itself, ignoring host
0233   e1->setField(QStringLiteral("imdb"), QLatin1String("https://www.imdb.com/title/tt1856080/"));
0234   e2->setField(QStringLiteral("imdb"), QLatin1String("https://us.imdb.com/title/tt1856080/"));
0235   e2->setField(QStringLiteral("title"), QString());
0236   e2->setField(QStringLiteral("year"), QString());
0237   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0238 }
0239 
0240 void EntryComparisonTest::testMusicMatch() {
0241   Tellico::Data::CollPtr c(new Tellico::Data::MusicCollection(true));
0242 
0243   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0244   e1->setField(QStringLiteral("title"), QStringLiteral("title1"));
0245   e1->setField(QStringLiteral("artist"), QStringLiteral("artist1"));
0246   e1->setField(QStringLiteral("label"), QStringLiteral("label"));
0247   e1->setField(QStringLiteral("year"), QStringLiteral("1994"));
0248   c->addEntries(e1);
0249 
0250   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0251   e2->setField(QStringLiteral("title"), QStringLiteral("title2"));
0252   e2->setField(QStringLiteral("artist"), QStringLiteral("artist2"));
0253 
0254   // not a good match
0255   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0256 
0257   // matching the title and artist makes a good match
0258   e2->setField(QStringLiteral("title"), QStringLiteral("title1"));
0259   e2->setField(QStringLiteral("artist"), QStringLiteral("artist1"));
0260   QVERIFY(c->sameEntry(e1, e2) > Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0261 
0262   e2->setField(QStringLiteral("label"), QStringLiteral("label"));
0263   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0264   e2->setField(QStringLiteral("label"), QString());
0265   e2->setField(QStringLiteral("year"), QStringLiteral("1994"));
0266   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0267 }
0268 
0269 void EntryComparisonTest::testGameMatch() {
0270   Tellico::Data::CollPtr c(new Tellico::Data::GameCollection(true));
0271 
0272   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0273   e1->setField(QStringLiteral("title"), QStringLiteral("title1"));
0274   e1->setField(QStringLiteral("platform"), QStringLiteral("Xbox One"));
0275   e1->setField(QStringLiteral("publisher"), QStringLiteral("publisher"));
0276   e1->setField(QStringLiteral("year"), QStringLiteral("1994"));
0277   c->addEntries(e1);
0278 
0279   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0280   e2->setField(QStringLiteral("title"), QStringLiteral("title2"));
0281   e2->setField(QStringLiteral("platform"), QStringLiteral("Xbox One"));
0282 
0283   // not a good match
0284   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0285 
0286   e2->setField(QStringLiteral("title"), QStringLiteral("title1"));
0287   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0288 
0289   e2->setField(QStringLiteral("publisher"), QStringLiteral("publisher"));
0290   e2->setField(QStringLiteral("year"), QStringLiteral("1994"));
0291   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0292 }
0293 
0294 void EntryComparisonTest::testFileMatch() {
0295   QUrl url = QUrl::fromLocalFile(QFINDTESTDATA("data/test.ris"));
0296   Tellico::Data::CollPtr c(new Tellico::Data::FileCatalog(true));
0297 
0298   // first check merging with same isbn
0299   Tellico::Data::EntryPtr e1(new Tellico::Data::Entry(c));
0300   e1->setField(QStringLiteral("url"), url.url());
0301   e1->setField(QStringLiteral("title"), QStringLiteral("file.name"));
0302   e1->setField(QStringLiteral("description"), QStringLiteral("desc"));
0303   e1->setField(QStringLiteral("mimetype"), QStringLiteral("text/plain"));
0304   e1->setField(QStringLiteral("size"), QStringLiteral("1234"));
0305   e1->setField(QStringLiteral("volume"), QStringLiteral("vol1"));
0306   c->addEntries(e1);
0307 
0308   Tellico::Data::EntryPtr e2(new Tellico::Data::Entry(c));
0309   e2->setField(QStringLiteral("url"), url.url());
0310   e2->setField(QStringLiteral("title"), QStringLiteral("file.name"));
0311 
0312   // perfect match by file url
0313   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0314 
0315   e2->setField(QStringLiteral("url"), QString());
0316   QVERIFY(c->sameEntry(e1, e2) == Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0317 
0318   e2->setField(QStringLiteral("description"), QStringLiteral("desc"));
0319   QVERIFY(c->sameEntry(e1, e2) > Tellico::EntryComparison::ENTRY_GOOD_MATCH);
0320   QVERIFY(c->sameEntry(e1, e2) < Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0321   e2->setField(QStringLiteral("mimetype"), QStringLiteral("text/plain"));
0322   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0323 
0324   e2->setField(QStringLiteral("description"), QString());
0325   e2->setField(QStringLiteral("mimetype"), QString());
0326   e2->setField(QStringLiteral("size"), QStringLiteral("1234"));
0327   QVERIFY(c->sameEntry(e1, e2) >= Tellico::EntryComparison::ENTRY_PERFECT_MATCH);
0328 
0329   // if volume is different, can't be same match
0330   e2->setField(QStringLiteral("volume"), QStringLiteral("vol2"));
0331   QVERIFY(c->sameEntry(e1, e2) <= Tellico::EntryComparison::ENTRY_BAD_MATCH);
0332 }