File indexing completed on 2024-04-21 03:53:39
0001 /* 0002 This file is part of the KDE libraries 0003 0004 SPDX-FileCopyrightText: 2021 Waqar Ahmed <waqar.17a@gmail.com> 0005 0006 SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 #include "kfuzzymatchertest.h" 0009 0010 #include <QString> 0011 #include <QStringList> 0012 #include <QTest> 0013 0014 #include <algorithm> 0015 0016 #include "kfuzzymatcher.h" 0017 0018 QTEST_MAIN(KFuzzyMatcherTest) 0019 0020 void KFuzzyMatcherTest::testMatchSimple_data() 0021 { 0022 QTest::addColumn<QString>("pattern"); 0023 QTest::addColumn<QString>("inputstr"); 0024 QTest::addColumn<bool>("expected"); 0025 0026 QTest::newRow("AbcD") << QStringLiteral("AbcD") << QStringLiteral("AbCdefg") << true; 0027 QTest::newRow("WithSpace") << QStringLiteral("Wa qa") << QStringLiteral("Wa qar") << true; 0028 QTest::newRow("RTL") << QStringLiteral("ارو") << QStringLiteral("اردو") << true; 0029 QTest::newRow("WithSep") << QStringLiteral("tf") << QStringLiteral("the_file") << true; 0030 QTest::newRow("Umlaut") << QStringLiteral("Häu") << QStringLiteral("Häuser") << true; 0031 QTest::newRow("Unmatched") << QStringLiteral("Name") << QStringLiteral("Nam") << false; 0032 QTest::newRow("Empty Pattern") << QStringLiteral("") << QStringLiteral("Nam") << true; 0033 } 0034 0035 void KFuzzyMatcherTest::testMatchSimple() 0036 { 0037 QFETCH(QString, pattern); 0038 QFETCH(QString, inputstr); 0039 QFETCH(bool, expected); 0040 0041 QVERIFY(KFuzzyMatcher::matchSimple(pattern, inputstr) == expected); 0042 } 0043 0044 void KFuzzyMatcherTest::testMatch_data() 0045 { 0046 QTest::addColumn<QString>("pattern"); 0047 QTest::addColumn<QStringList>("input"); 0048 QTest::addColumn<QStringList>("expected"); 0049 QTest::addColumn<int>("size"); 0050 // clang-format off 0051 QTest::newRow("pattern=sort") << QStringLiteral("sort") 0052 << QStringList{ 0053 QStringLiteral("Sort"), 0054 QStringLiteral("Some other right test"), 0055 QStringLiteral("Soup rate"), 0056 QStringLiteral("Someother"), 0057 QStringLiteral("irrelevant"), 0058 } 0059 << QStringList{ 0060 QStringLiteral("Sort"), 0061 QStringLiteral("Some other right test"), 0062 QStringLiteral("Soup rate"), 0063 } 0064 << 3; 0065 0066 0067 QTest::newRow("pattern=kateapp") << QStringLiteral("kaapp") 0068 << QStringList{ 0069 QStringLiteral("kateapp.cpp"), 0070 QStringLiteral("kate_application"), 0071 QStringLiteral("kateapp.h"), 0072 QStringLiteral("katepap.c") 0073 } 0074 << QStringList{ 0075 QStringLiteral("kate_application"), 0076 QStringLiteral("kateapp.h"), 0077 QStringLiteral("kateapp.cpp") 0078 } 0079 << 3; 0080 0081 QTest::newRow("pattern=this") << QStringLiteral("this") 0082 << QStringList{ 0083 QStringLiteral("th"), 0084 QStringLiteral("ths"), 0085 QStringLiteral("thsi") 0086 } 0087 << QStringList{ 0088 } 0089 << 0; 0090 0091 QTest::newRow("pattern=marath") << QStringLiteral("marath") 0092 << QStringList{ 0093 QStringLiteral("Maralen of the Mornsong"), 0094 QStringLiteral("Silumgar, the Drifting Death"), 0095 QStringLiteral("Maralen of the Mornsong Avatar"), 0096 QStringLiteral("Marshaling the Troops"), 0097 QStringLiteral("Homeward Path"), 0098 QStringLiteral("Marath, Will of the Wild"), 0099 QStringLiteral("Marshal's Anthem"), 0100 QStringLiteral("Marchesa, the Black Rose"), 0101 QStringLiteral("Mark for Death"), 0102 QStringLiteral("Master Apothecary"), 0103 QStringLiteral("Mazirek, Kraul Death Priest"), 0104 QStringLiteral("Akroma, Angel of Wrath"), 0105 QStringLiteral("Akroma, Angel of Wrath Avatar"), 0106 QStringLiteral("Commander's Authority"), 0107 QStringLiteral("Shaman of the Great Hunt"), 0108 QStringLiteral("Halimar Wavewatch"), 0109 QStringLiteral("Pyromancer's Swath") 0110 } 0111 << QStringList{ 0112 QStringLiteral("Marath, Will of the Wild"), 0113 QStringLiteral("Maralen of the Mornsong"), 0114 QStringLiteral("Maralen of the Mornsong Avatar"), 0115 QStringLiteral("Marshal's Anthem"), 0116 QStringLiteral("Marshaling the Troops"), 0117 QStringLiteral("Marchesa, the Black Rose"), 0118 QStringLiteral("Mark for Death"), 0119 QStringLiteral("Master Apothecary"), 0120 QStringLiteral("Mazirek, Kraul Death Priest"), 0121 QStringLiteral("Akroma, Angel of Wrath"), 0122 QStringLiteral("Akroma, Angel of Wrath Avatar"), 0123 QStringLiteral("Commander's Authority"), 0124 QStringLiteral("Homeward Path"), 0125 QStringLiteral("Shaman of the Great Hunt"), 0126 QStringLiteral("Halimar Wavewatch"), 0127 QStringLiteral("Pyromancer's Swath"), 0128 QStringLiteral("Silumgar, the Drifting Death") 0129 } 0130 << 17; 0131 0132 // This tests our recursive best match 0133 QTest::newRow("pattern=lll") << QStringLiteral("lll") 0134 << QStringList{ 0135 QStringLiteral("SVisualLoggerLogsList.h"), 0136 QStringLiteral("SimpleFileLogger.cpp"), 0137 QStringLiteral("StringHandlerLogList.txt"), 0138 QStringLiteral("LeapFromLostAllan"), 0139 QStringLiteral("BumpLLL"), 0140 } 0141 << QStringList{ 0142 QStringLiteral("SVisualLoggerLogsList.h"), 0143 QStringLiteral("LeapFromLostAllan"), 0144 QStringLiteral("BumpLLL"), 0145 QStringLiteral("StringHandlerLogList.txt"), 0146 QStringLiteral("SimpleFileLogger.cpp"), 0147 } 0148 << 5; 0149 0150 QTest::newRow("pattern=") << QStringLiteral("") 0151 << QStringList{ 0152 QStringLiteral("th"), 0153 QStringLiteral("ths"), 0154 QStringLiteral("thsi") 0155 } 0156 << QStringList{ 0157 QStringLiteral("th"), 0158 QStringLiteral("ths"), 0159 QStringLiteral("thsi") 0160 } 0161 << 3; 0162 // clang-format on 0163 } 0164 0165 static QStringList matchHelper(const QString &pattern, const QStringList &input) 0166 { 0167 QList<QPair<QString, int>> actual; 0168 for (int i = 0; i < input.size(); ++i) { 0169 KFuzzyMatcher::Result res = KFuzzyMatcher::match(pattern, input.at(i)); 0170 if (res.matched) { 0171 actual.push_back({input.at(i), res.score}); 0172 } 0173 } 0174 0175 // sort descending based on score 0176 std::sort(actual.begin(), actual.end(), [](const QPair<QString, int> &l, const QPair<QString, int> &r) { 0177 return l.second > r.second; 0178 }); 0179 0180 QStringList actualOut; 0181 for (const auto &s : actual) { 0182 actualOut << s.first; 0183 } 0184 return actualOut; 0185 } 0186 0187 void KFuzzyMatcherTest::testMatch() 0188 { 0189 QFETCH(QString, pattern); 0190 QFETCH(QStringList, input); 0191 QFETCH(QStringList, expected); 0192 QFETCH(int, size); 0193 0194 const QStringList actual = matchHelper(pattern, input); 0195 0196 QCOMPARE(actual.size(), size); 0197 QCOMPARE(actual, expected); 0198 } 0199 0200 void KFuzzyMatcherTest::testMatchedRanges_data() 0201 { 0202 QTest::addColumn<QString>("pattern"); 0203 QTest::addColumn<QString>("string"); 0204 0205 using Range = QPair<int, int>; 0206 QTest::addColumn<QList<Range>>("expectedRanges"); 0207 0208 QTest::addColumn<bool>("matchingOnly"); 0209 0210 QTest::newRow("Emtpy") << QStringLiteral("") << QStringLiteral("") << QList<Range>{} << true; 0211 QTest::newRow("Hello") << QStringLiteral("Hlo") << QStringLiteral("Hello") << QList<Range>{{0, 1}, {3, 2}} << true; 0212 QTest::newRow("lll") << QStringLiteral("lll") << QStringLiteral("SVisualLoggerLogsList") << QList<Range>{{7, 1}, {13, 1}, {17, 1}} << true; 0213 QTest::newRow("Sort") << QStringLiteral("sort") << QStringLiteral("SorT") << QList<Range>{{0, 4}} << true; 0214 QTest::newRow("Unmatching") << QStringLiteral("git") << QStringLiteral("gti") << QList<Range>{} << true; 0215 QTest::newRow("UnmatchingWithAllMatches") << QStringLiteral("git") << QStringLiteral("gti") << QList<Range>{{0, 1}, {2, 1}} << false; 0216 } 0217 0218 void KFuzzyMatcherTest::testMatchedRanges() 0219 { 0220 QFETCH(QString, pattern); 0221 QFETCH(QString, string); 0222 QFETCH(bool, matchingOnly); 0223 using Range = QPair<int, int>; 0224 QFETCH(QList<Range>, expectedRanges); 0225 0226 const auto matchMode = matchingOnly ? KFuzzyMatcher::RangeType::FullyMatched : KFuzzyMatcher::RangeType::All; 0227 0228 auto resultRanges = KFuzzyMatcher::matchedRanges(pattern, string, matchMode); 0229 QCOMPARE(resultRanges.size(), expectedRanges.size()); 0230 0231 bool res = std::equal(expectedRanges.begin(), expectedRanges.end(), resultRanges.begin(), [](const Range &l, const KFuzzyMatcher::Range &r) { 0232 return l.first == r.start && l.second == r.length; 0233 }); 0234 QVERIFY(res); 0235 } 0236 0237 #include "moc_kfuzzymatchertest.cpp"