File indexing completed on 2024-05-12 05:09:59
0001 /*************************************************************************** 0002 Copyright (C) 2011 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 #undef QT_NO_CAST_FROM_ASCII 0026 0027 #include "filtertest.h" 0028 0029 #include "../filter.h" 0030 #include "../entry.h" 0031 #include "../collections/bookcollection.h" 0032 #include "../collections/videocollection.h" 0033 #include "../images/imageinfo.h" 0034 #include "../images/imagefactory.h" 0035 0036 #include <KLocalizedString> 0037 0038 #include <QTest> 0039 #include <QStandardPaths> 0040 0041 QTEST_GUILESS_MAIN( FilterTest ) 0042 0043 void FilterTest::initTestCase() { 0044 QStandardPaths::setTestModeEnabled(true); 0045 KLocalizedString::setApplicationDomain("tellico"); 0046 Tellico::ImageFactory::init(); 0047 } 0048 0049 void FilterTest::testFilter() { 0050 Tellico::Data::CollPtr coll(new Tellico::Data::Collection(true, QStringLiteral("TestCollection"))); 0051 Tellico::Data::EntryPtr entry(new Tellico::Data::Entry(coll)); 0052 entry->setField(QStringLiteral("title"), QStringLiteral("Star Wars")); 0053 0054 Tellico::FilterRule* rule1 = new Tellico::FilterRule(QStringLiteral("title"), 0055 QStringLiteral("Star Wars"), 0056 Tellico::FilterRule::FuncEquals); 0057 QCOMPARE(rule1->fieldName(), QStringLiteral("title")); 0058 QCOMPARE(rule1->pattern(), QStringLiteral("Star Wars")); 0059 QCOMPARE(rule1->function(), Tellico::FilterRule::FuncEquals); 0060 0061 Tellico::Filter filter(Tellico::Filter::MatchAny); 0062 filter.append(rule1); 0063 QVERIFY(filter.matches(entry)); 0064 rule1->setFunction(Tellico::FilterRule::FuncNotEquals); 0065 QVERIFY(!filter.matches(entry)); 0066 0067 rule1->setFunction(Tellico::FilterRule::FuncContains); 0068 QVERIFY(filter.matches(entry)); 0069 0070 rule1->setFieldName(QStringLiteral("author")); 0071 QVERIFY(!filter.matches(entry)); 0072 rule1->setFunction(Tellico::FilterRule::FuncNotContains); 0073 QVERIFY(filter.matches(entry)); 0074 0075 rule1->setFieldName(QString()); 0076 rule1->setFunction(Tellico::FilterRule::FuncEquals); 0077 QVERIFY(filter.matches(entry)); 0078 0079 Tellico::FilterRule* rule2 = new Tellico::FilterRule(QStringLiteral("title"), 0080 QStringLiteral("Star"), 0081 Tellico::FilterRule::FuncEquals); 0082 filter.clear(); 0083 filter.append(rule2); 0084 QVERIFY(!filter.matches(entry)); 0085 0086 rule2->setFunction(Tellico::FilterRule::FuncContains); 0087 QVERIFY(filter.matches(entry)); 0088 rule2->setFunction(Tellico::FilterRule::FuncNotContains); 0089 QVERIFY(!filter.matches(entry)); 0090 0091 rule2->setFieldName(QStringLiteral("author")); 0092 rule2->setFunction(Tellico::FilterRule::FuncContains); 0093 QVERIFY(!filter.matches(entry)); 0094 0095 rule2->setFieldName(QString()); 0096 QVERIFY(filter.matches(entry)); 0097 0098 Tellico::FilterRule* rule3 = new Tellico::FilterRule(QStringLiteral("title"), 0099 QStringLiteral("Sta[rt]"), 0100 Tellico::FilterRule::FuncRegExp); 0101 QCOMPARE(rule3->pattern(), QStringLiteral("Sta[rt]")); 0102 filter.clear(); 0103 filter.append(rule3); 0104 QVERIFY(filter.matches(entry)); 0105 0106 rule3->setFunction(Tellico::FilterRule::FuncNotRegExp); 0107 QVERIFY(!filter.matches(entry)); 0108 0109 rule3->setFieldName(QStringLiteral("author")); 0110 QVERIFY(filter.matches(entry)); 0111 0112 rule3->setFieldName(QString()); 0113 rule3->setFunction(Tellico::FilterRule::FuncRegExp); 0114 QVERIFY(filter.matches(entry)); 0115 0116 entry->setField(QStringLiteral("title"), QStringLiteral("Tmavomodrý Svět")); 0117 0118 Tellico::FilterRule* rule4 = new Tellico::FilterRule(QStringLiteral("title"), 0119 QStringLiteral("Tmavomodrý Svět"), 0120 Tellico::FilterRule::FuncEquals); 0121 filter.clear(); 0122 filter.append(rule4); 0123 QVERIFY(filter.matches(entry)); 0124 0125 rule4->setFunction(Tellico::FilterRule::FuncContains); 0126 QVERIFY(filter.matches(entry)); 0127 0128 rule4->setFunction(Tellico::FilterRule::FuncRegExp); 0129 QVERIFY(filter.matches(entry)); 0130 0131 Tellico::FilterRule* rule5 = new Tellico::FilterRule(QStringLiteral("title"), 0132 QStringLiteral("Tmavomodry Svet"), 0133 Tellico::FilterRule::FuncEquals); 0134 0135 filter.clear(); 0136 filter.append(rule5); 0137 QVERIFY(!filter.matches(entry)); 0138 0139 rule5->setFunction(Tellico::FilterRule::FuncContains); 0140 QVERIFY(filter.matches(entry)); 0141 0142 rule5->setFunction(Tellico::FilterRule::FuncRegExp); 0143 QVERIFY(!filter.matches(entry)); 0144 0145 Tellico::Data::FieldPtr date(new Tellico::Data::Field(QStringLiteral("date"), 0146 QStringLiteral("Date"), 0147 Tellico::Data::Field::Date)); 0148 coll->addField(date); 0149 0150 Tellico::FilterRule* rule6 = new Tellico::FilterRule(QStringLiteral("date"), 0151 QStringLiteral("2011-01-24"), 0152 Tellico::FilterRule::FuncAfter); 0153 QCOMPARE(rule6->pattern(), QStringLiteral("2011-01-24")); 0154 filter.clear(); 0155 filter.append(rule6); 0156 // test Bug 361625 0157 entry->setField(QStringLiteral("date"), QStringLiteral("2011-1-25")); 0158 QVERIFY(filter.matches(entry)); 0159 entry->setField(QStringLiteral("date"), QStringLiteral("2011-01-25")); 0160 QVERIFY(filter.matches(entry)); 0161 0162 rule6->setFunction(Tellico::FilterRule::FuncBefore); 0163 QVERIFY(!filter.matches(entry)); 0164 0165 // check that a date match is neither before or after 0166 entry->setField(QStringLiteral("date"), rule6->pattern()); 0167 rule6->setFunction(Tellico::FilterRule::FuncAfter); 0168 QVERIFY(!filter.matches(entry)); 0169 rule6->setFunction(Tellico::FilterRule::FuncBefore); 0170 QVERIFY(!filter.matches(entry)); 0171 0172 // check that an invalid date never matches 0173 entry->setField(QStringLiteral("date"), QStringLiteral("test")); 0174 rule6->setFunction(Tellico::FilterRule::FuncAfter); 0175 QVERIFY(!filter.matches(entry)); 0176 rule6->setFunction(Tellico::FilterRule::FuncBefore); 0177 QVERIFY(!filter.matches(entry)); 0178 0179 Tellico::Data::FieldPtr number(new Tellico::Data::Field(QStringLiteral("number"), 0180 QStringLiteral("Number"), 0181 Tellico::Data::Field::Number)); 0182 coll->addField(number); 0183 entry->setField(QStringLiteral("number"), QStringLiteral("3")); 0184 0185 Tellico::FilterRule* rule7 = new Tellico::FilterRule(QStringLiteral("number"), 0186 QStringLiteral("5.0"), 0187 Tellico::FilterRule::FuncLess); 0188 QCOMPARE(rule7->pattern(), QStringLiteral("5.0")); 0189 filter.clear(); 0190 filter.append(rule7); 0191 QVERIFY(filter.matches(entry)); 0192 0193 rule7->setFunction(Tellico::FilterRule::FuncGreater); 0194 QVERIFY(!filter.matches(entry)); 0195 0196 entry->setField(QStringLiteral("number"), QStringLiteral("6")); 0197 QVERIFY(filter.matches(entry)); 0198 0199 // check that a rating can use greater than 0200 Tellico::Data::FieldPtr rating(new Tellico::Data::Field(QStringLiteral("rating"), 0201 QStringLiteral("Rating"), 0202 Tellico::Data::Field::Rating)); 0203 coll->addField(rating); 0204 entry->setField(QStringLiteral("rating"), QStringLiteral("3")); 0205 0206 Tellico::FilterRule* rule8 = new Tellico::FilterRule(QStringLiteral("rating"), 0207 QStringLiteral("2.0"), 0208 Tellico::FilterRule::FuncGreater); 0209 QCOMPARE(rule8->pattern(), QStringLiteral("2.0")); 0210 filter.clear(); 0211 filter.append(rule8); 0212 QVERIFY(filter.matches(entry)); 0213 0214 rule8->setFunction(Tellico::FilterRule::FuncLess); 0215 QVERIFY(!filter.matches(entry)); 0216 0217 entry->setField(QStringLiteral("rating"), QStringLiteral("1")); 0218 QVERIFY(filter.matches(entry)); 0219 0220 // check image size comparisons 0221 Tellico::Data::FieldPtr imageField(new Tellico::Data::Field(QStringLiteral("image"), 0222 QStringLiteral("image"), 0223 Tellico::Data::Field::Image)); 0224 coll->addField(imageField); 0225 const QString imageName(QStringLiteral("image.png")); 0226 entry->setField(QStringLiteral("image"), imageName); 0227 // insert image size into cache (128x128) 0228 Tellico::Data::ImageInfo imageInfo(imageName, "PNG", 128, 96, false); 0229 Tellico::ImageFactory::cacheImageInfo(imageInfo); 0230 0231 Tellico::FilterRule* rule9 = new Tellico::FilterRule(QStringLiteral("image"), 0232 QStringLiteral("96"), 0233 Tellico::FilterRule::FuncGreater); 0234 QVERIFY(!rule9->isEmpty()); 0235 QCOMPARE(rule9->pattern(), QStringLiteral("96")); 0236 filter.clear(); 0237 filter.append(rule9); 0238 // compares against larger image dimension, so 128 > 96 matches 0239 QVERIFY(filter.matches(entry)); 0240 0241 // compares against larger image dimension, so 128 < 96 fails 0242 rule9->setFunction(Tellico::FilterRule::FuncLess); 0243 QVERIFY(!filter.matches(entry)); 0244 0245 Tellico::Data::ImageInfo imageInfo2(imageName, "PNG", 96, 96, false); 0246 Tellico::ImageFactory::cacheImageInfo(imageInfo2); 0247 0248 rule9->setFunction(Tellico::FilterRule::FuncLess); 0249 QVERIFY(!filter.matches(entry)); 0250 rule9->setFunction(Tellico::FilterRule::FuncEquals); 0251 QVERIFY(filter.matches(entry)); 0252 // an empty image should also match less than size 0253 entry->setField(QStringLiteral("image"), QString()); 0254 rule9->setFunction(Tellico::FilterRule::FuncLess); 0255 QVERIFY(filter.matches(entry)); 0256 0257 // test a filter for matching against an empty string 0258 Tellico::Data::FieldPtr testField(new Tellico::Data::Field(QStringLiteral("test"), 0259 QStringLiteral("Test"))); 0260 coll->addField(testField); 0261 Tellico::FilterRule* rule10 = new Tellico::FilterRule(QStringLiteral("test"), 0262 QString(), 0263 Tellico::FilterRule::FuncEquals); 0264 QVERIFY(!rule10->isEmpty()); 0265 filter.clear(); 0266 filter.append(rule10); 0267 QVERIFY(filter.matches(entry)); 0268 rule10->setFunction(Tellico::FilterRule::FuncNotEquals); 0269 QVERIFY(!rule10->isEmpty()); 0270 QVERIFY(!filter.matches(entry)); 0271 } 0272 0273 void FilterTest::testGroupViewFilter() { 0274 // ideally, I'd instantiate a GroupView object and test that, but it's tough with all the dependencies 0275 // so this code is identical to what is in Tellico::GroupView::slotFilterGroup() 0276 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true, QStringLiteral("TestCollection"))); 0277 Tellico::Data::EntryPtr entry1(new Tellico::Data::Entry(coll)); 0278 entry1->setField(QStringLiteral("author"), QStringLiteral("John Author")); 0279 Tellico::Data::EntryPtr entry2(new Tellico::Data::Entry(coll)); 0280 entry2->setField(QStringLiteral("author"), QStringLiteral("John Q. Author")); 0281 Tellico::Data::EntryPtr entry3(new Tellico::Data::Entry(coll)); 0282 entry3->setField(QStringLiteral("author"), QStringLiteral("John Author") + 0283 Tellico::FieldFormat::delimiterString() + 0284 QStringLiteral("James Author")); 0285 Tellico::Data::EntryPtr entry4(new Tellico::Data::Entry(coll)); 0286 entry4->setField(QStringLiteral("author"), QStringLiteral("James Author") + 0287 Tellico::FieldFormat::delimiterString() + 0288 QStringLiteral("John Author")); 0289 Tellico::Data::EntryPtr entry5(new Tellico::Data::Entry(coll)); 0290 entry5->setField(QStringLiteral("author"), QStringLiteral("James Author") + 0291 Tellico::FieldFormat::delimiterString() + 0292 QStringLiteral("John Q. Author")); 0293 0294 QString pattern(entry1->formattedField(QStringLiteral("author"))); 0295 // the filter should match all since it was the initial way the group view filter was constructed 0296 Tellico::Filter filter1(Tellico::Filter::MatchAny); 0297 filter1.append(new Tellico::FilterRule(QStringLiteral("author"), pattern, Tellico::FilterRule::FuncContains)); 0298 QVERIFY(filter1.matches(entry1)); 0299 QVERIFY(filter1.matches(entry2)); 0300 QVERIFY(filter1.matches(entry3)); 0301 QVERIFY(filter1.matches(entry4)); 0302 QVERIFY(filter1.matches(entry5)); 0303 0304 QString rxPattern = Tellico::FieldFormat::matchValueRegularExpression(pattern); 0305 // the filter should match entry1, entry3, and entry 4 but not entry2 or entry5 0306 Tellico::Filter filter2(Tellico::Filter::MatchAny); 0307 filter2.append(new Tellico::FilterRule(QStringLiteral("author"), rxPattern, Tellico::FilterRule::FuncRegExp)); 0308 QVERIFY(filter2.matches(entry1)); 0309 QVERIFY(!filter2.matches(entry2)); // does not match 0310 QVERIFY(filter2.matches(entry3)); 0311 QVERIFY(filter2.matches(entry4)); 0312 QVERIFY(!filter2.matches(entry5)); 0313 0314 // Bug 415886 0315 Tellico::Data::CollPtr coll2(new Tellico::Data::VideoCollection(true, QStringLiteral("TestCollection2"))); 0316 Tellico::Data::EntryPtr movie(new Tellico::Data::Entry(coll2)); 0317 movie->setField(QStringLiteral("cast"), QStringLiteral("John Author") + 0318 Tellico::FieldFormat::columnDelimiterString() + 0319 QStringLiteral("role")); 0320 Tellico::Filter castFilter(Tellico::Filter::MatchAny); 0321 castFilter.append(new Tellico::FilterRule(QStringLiteral("cast"), rxPattern, Tellico::FilterRule::FuncRegExp)); 0322 // single table row with value 0323 QVERIFY(castFilter.matches(movie)); 0324 movie->setField(QStringLiteral("cast"), QStringLiteral("John Author") + 0325 Tellico::FieldFormat::rowDelimiterString() + 0326 QStringLiteral("Second Author")); 0327 // multiple table row with value only 0328 QVERIFY(castFilter.matches(movie)); 0329 movie->setField(QStringLiteral("cast"), QStringLiteral("No one") + 0330 Tellico::FieldFormat::rowDelimiterString() + 0331 QStringLiteral("John Author") + 0332 Tellico::FieldFormat::rowDelimiterString() + 0333 QStringLiteral("Second Author")); 0334 // multiple table row with value second 0335 QVERIFY(castFilter.matches(movie)); 0336 } 0337 0338 void FilterTest::testQuickFilter() { 0339 Tellico::Data::CollPtr coll(new Tellico::Data::BookCollection(true, QStringLiteral("TestCollection"))); 0340 Tellico::Data::EntryPtr entry(new Tellico::Data::Entry(coll)); 0341 entry->setField(QStringLiteral("title"), QStringLiteral("C++ Coding Standards")); 0342 0343 Tellico::FilterPtr filter(new Tellico::Filter(Tellico::Filter::MatchAll)); 0344 QString fieldName; // empty means any field 0345 0346 Tellico::Filter::populateQuickFilter(filter, fieldName, QStringLiteral("C++"), true /* allow regexps */); 0347 QVERIFY(filter->matches(entry)); 0348 0349 entry->setField(QStringLiteral("title"), QStringLiteral("Coding Standards")); 0350 QVERIFY(filter->matches(entry)); // still matches due to c++ being interpreted as a regexp 0351 0352 Tellico::FilterPtr filter2(new Tellico::Filter(Tellico::Filter::MatchAll)); 0353 0354 Tellico::Filter::populateQuickFilter(filter2, fieldName, QStringLiteral("C++"), false /* allow regexps */); 0355 entry->setField(QStringLiteral("title"), QStringLiteral("C++ Coding Standards")); 0356 QVERIFY(filter2->matches(entry)); 0357 0358 entry->setField(QStringLiteral("title"), QStringLiteral("Coding Standards")); 0359 QVERIFY(!filter2->matches(entry)); // no longer matches 0360 }