diff options
-rw-r--r-- | lib/urlfilter/formats/adblockrule.cpp | 1 | ||||
-rw-r--r-- | lib/urlfilter/formats/adblockrule.h | 58 | ||||
-rw-r--r-- | lib/urlfilter/formats/adblockrule_parse.cpp | 2 | ||||
-rw-r--r-- | lib/urlfilter/formats/adblockrule_parse.h | 4 | ||||
-rw-r--r-- | meson.build | 4 | ||||
-rw-r--r-- | meson_options.txt | 2 | ||||
-rw-r--r-- | test/adblock/adblocktest.cpp | 124 | ||||
-rw-r--r-- | test/adblock/adblocktest.h | 15 | ||||
-rw-r--r-- | test/meson.build | 6 |
9 files changed, 142 insertions, 74 deletions
diff --git a/lib/urlfilter/formats/adblockrule.cpp b/lib/urlfilter/formats/adblockrule.cpp index db1c3c5..60e817f 100644 --- a/lib/urlfilter/formats/adblockrule.cpp +++ b/lib/urlfilter/formats/adblockrule.cpp @@ -45,6 +45,7 @@ bool AdBlockRule::match(const QUrl &requestUrl, QWebEngineUrlRequestInfo::Resour case FilterLeaf::RegularExpressionMatch: return (regExp->indexIn(requestUrl.toString()) != -1); default: + qWarning("Match type not implemented, returning false!"); return false; } } diff --git a/lib/urlfilter/formats/adblockrule.h b/lib/urlfilter/formats/adblockrule.h index 9c89dac..3331cac 100644 --- a/lib/urlfilter/formats/adblockrule.h +++ b/lib/urlfilter/formats/adblockrule.h @@ -11,6 +11,64 @@ #include "../filterleaf.h" #include <optional> +#include <QRegularExpression> +#include <QStringMatcher> + +template <typename T> +class ContentsMatcher +{ +public: + ContentsMatcher(const QString &pattern, FilterLeaf::UrlMatchType matchType) + { + this->matchType = matchType; + patternLength = pattern.length(); + matcher.setPattern(pattern); + + if constexpr(std::is_same_v<T, QRegularExpression>) { + matcher.setPatternOptions(matcher.patternOptions() | QRegularExpression::CaseInsensitiveOption); + } else if constexpr(std::is_same_v<T, QStringMatcher>) { + matcher.setCaseSensitivity(Qt::CaseInsensitive); + } + } + + bool hasMatch(const QString &where) const + { + if constexpr(std::is_same_v<T, QStringMatcher>) { + switch (matchType) { + case FilterLeaf::InvalidMatch: + case FilterLeaf::RegularExpressionMatch: + case FilterLeaf::DomainMatch: + qWarning("ContentsMatcher is a String Matcher, but not doing string matching!"); + return false; + + case FilterLeaf::StringContains: + return (matcher.indexIn(where) != -1); + + case FilterLeaf::StringStartsWith: + return (matcher.indexIn(where) == 0); + + case FilterLeaf::StringEndsWith: + return (matcher.indexIn(where) == where.length() - patternLength); + + case FilterLeaf::StringEquals: + return (matcher.indexIn(where) == 0) && (patternLength == where.length()); + } + + } else if constexpr(std::is_same_v<T, QRegularExpression>) { + if(matchType != FilterLeaf::RegularExpressionMatch) + qWarning("ContentsMatcher is a regular expression, but not doing a regular expression match!"); + return matcher.match(where).hasMatch(); + } else { + qWarning("Matcher has no backend, returning false"); + return false; + } + } + +private: + int patternLength; + T matcher; + FilterLeaf::UrlMatchType matchType; +}; class AdBlockRule : public FilterLeaf { diff --git a/lib/urlfilter/formats/adblockrule_parse.cpp b/lib/urlfilter/formats/adblockrule_parse.cpp index 0e5bf05..927a6a3 100644 --- a/lib/urlfilter/formats/adblockrule_parse.cpp +++ b/lib/urlfilter/formats/adblockrule_parse.cpp @@ -16,7 +16,7 @@ // QString::chop(len) - Removes n characters from the end of the string. // QString::remove(pos, len) - Removes n characters from the string, starting at the given position index. -AdBlockRule *loadRule(const QString &filter) +AdBlockRule *parseRule_adblock(const QString &filter) { QString parsedLine = filter.trimmed(); diff --git a/lib/urlfilter/formats/adblockrule_parse.h b/lib/urlfilter/formats/adblockrule_parse.h index 7d380a8..01255ca 100644 --- a/lib/urlfilter/formats/adblockrule_parse.h +++ b/lib/urlfilter/formats/adblockrule_parse.h @@ -11,7 +11,7 @@ class AdBlockRule; -AdBlockRule *loadRule(const QString &filter); +AdBlockRule *parseRule_adblock(const QString &filter); std::optional<QPair<QWebEngineUrlRequestInfo::ResourceType, bool>> parseOption(const QString &option); -#endif // ADBLOCKRULE_PARSE_H
\ No newline at end of file +#endif // ADBLOCKRULE_PARSE_H diff --git a/meson.build b/meson.build index 9c2f0d3..5452574 100644 --- a/meson.build +++ b/meson.build @@ -76,5 +76,7 @@ subdir('doc') subdir('plugins/ConfigurationEditor') subdir('plugins/ProfileEditor') -subdir('test') +if get_option('testing').enabled() + subdir('test') +endif diff --git a/meson_options.txt b/meson_options.txt index ee219a7..5362f95 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -9,3 +9,5 @@ option('translations', description: 'Generate and install translations', type: ' # Feature options option('Breakpad', description: 'Enable breakpad crash reporting', type: 'feature', value: 'auto') option('Plasma', description: 'Enable KDE plasma integration', type: 'feature', value: 'auto') +option('testing', description: 'Build tests (requires gtest)', type: 'feature', value: 'auto') + diff --git a/test/adblock/adblocktest.cpp b/test/adblock/adblocktest.cpp index 871b7ca..bbcaf0e 100644 --- a/test/adblock/adblocktest.cpp +++ b/test/adblock/adblocktest.cpp @@ -1,65 +1,83 @@ -#include "adblocktest.h" -#include <QtTest/QtTest> #include "formats/adblockrule.h" #include "formats/adblockrule_parse.h" +#include <gtest/gtest.h> -void AdBlockTest::parseRule() -{ - auto *rule = loadRule("/spamdomain/$domain=spamdomain.com,image"); - QCOMPARE(rule != nullptr, true); - QCOMPARE(rule->match(QUrl::fromUserInput("subdomain.spamdomain.com")), true); - QCOMPARE(rule->action().first == FilterLeaf::Block, true); - QCOMPARE(rule->option(QWebEngineUrlRequestInfo::ResourceTypeImage).value(), true); +TEST(Matcher, StringContains) { + ContentsMatcher<QStringMatcher> matcher("spam-pattern", FilterLeaf::StringContains); + EXPECT_TRUE(matcher.hasMatch("this string contains a spam-pattern")); + EXPECT_FALSE(matcher.hasMatch("this string does not contain the pattern")); } -/*void AdBlockTest::parseList() -{ - std::vector<AdBlockRule> rules; +TEST(Matcher, StringStartsWith) { + ContentsMatcher<QStringMatcher> matcher("beginning", FilterLeaf::StringStartsWith); + EXPECT_TRUE(matcher.hasMatch("beginning this string is the pattern")); + EXPECT_FALSE(matcher.hasMatch("ending this string is the pattern, the word beginning")); + EXPECT_FALSE(matcher.hasMatch("this would be a string where the pattern cannot be found")); +} + +TEST(Matcher, StringEndsWith) { + ContentsMatcher<QStringMatcher> matcher("ending", FilterLeaf::StringEndsWith); + EXPECT_TRUE(matcher.hasMatch("this string has the proper ending")); + EXPECT_FALSE(matcher.hasMatch("and this string doesn't")); +} + +TEST(Matcher, StringEquals) { + ContentsMatcher<QStringMatcher> matcher("string-to-match", FilterLeaf::StringEquals); + EXPECT_TRUE(matcher.hasMatch("string-to-match")); + EXPECT_FALSE(matcher.hasMatch("same-len-string")); + EXPECT_FALSE(matcher.hasMatch("not the string-to-match")); +} + +TEST(Matcher, RegularExpression) { + ContentsMatcher<QRegularExpression> matcher("banner\\d+", FilterLeaf::RegularExpressionMatch); + EXPECT_TRUE(matcher.hasMatch("http://another.com/banner123")); + EXPECT_TRUE(matcher.hasMatch("http://another.com/banner321")); + EXPECT_FALSE(matcher.hasMatch("http://another.com/banners")); + +} - QFile list("adblock.txt"); - int ruleCount = 0; - QCOMPARE(list.open(QIODevice::ReadOnly | QIODevice::Text), true); - { - QTextStream l(&list); - QString line; - while(l.readLineInto(&line)) { - AdBlockRule rule(line); - if(rule.isEnabled()) { - rules.emplace_back(std::move(rule)); - ruleCount++; - qDebug("added rule: %s", qUtf8Printable(line)); - } - } - } - list.close(); +TEST(AdBlockRule, SimpleRule) { + AdBlockRule *rule = parseRule_adblock("/spamdomain/$domain=spamdomain.com,image"); + EXPECT_TRUE(rule->match(QUrl("subdomain.spamdomain.com"))); +// QCOMPARE(rule->action().first == FilterLeaf::Block, true); +// QCOMPARE(rule->option(QWebEngineUrlRequestInfo::ResourceTypeImage).value(), true); +} - // there should be 3 rules - QCOMPARE(rules.size(), ruleCount); +TEST(AdBlockRule, AddressPart) { + AdBlockRule *rule = parseRule_adblock("/banner/*/img^"); + EXPECT_TRUE(rule->match(QUrl("http://example.com/banner/foo/img"))); + EXPECT_TRUE(rule->match(QUrl("http://example.com/banner/foo/bar/img?param"))); + EXPECT_TRUE(rule->match(QUrl("http://example.com/banner//img/foo"))); + EXPECT_FALSE(rule->match(QUrl("http://example.com/banner/img"))); + EXPECT_FALSE(rule->match(QUrl("http://example.com/banner/foo/imgraph"))); + EXPECT_FALSE(rule->match(QUrl("http://example.com/banner/foo/img.gif"))); +} - // block by address part - QCOMPARE(check(rules, QUrl("http://example.com/banner/foo/img")), true); - QCOMPARE(check(rules, QUrl("http://example.com/banner/foo/bar/img?param")), true); - QCOMPARE(check(rules, QUrl("http://example.com/banner//img/foo")), true); - QCOMPARE(check(rules, QUrl("http://example.com/banner/img")), false); - QCOMPARE(check(rules, QUrl("http://example.com/banner/foo/imgraph")), false); - QCOMPARE(check(rules, QUrl("http://example.com/banner/foo/img.gif")), false); +TEST(AdBlockRule, Domain){ + AdBlockRule *rule = parseRule_adblock("||ads.example.com^"); + EXPECT_TRUE(rule->match(QUrl("http://ads.example.com/foo.gif"))); + EXPECT_TRUE(rule->match(QUrl("http://server1.ads.example.com/foo.gif"))); + EXPECT_TRUE(rule->match(QUrl("https://ads.example.com:8000/"))); + EXPECT_FALSE(rule->match(QUrl("http://ads.example.com.ua/foo.gif"))); + EXPECT_FALSE(rule->match(QUrl("http://example.com/redirect/http://ads.example.com/"))); +} - // block by domain - QCOMPARE(check(rules, QUrl("http://ads.example.com/foo.gif")), true); - QCOMPARE(check(rules, QUrl("http://server1.ads.example.com/foo.gif")), true); - QCOMPARE(check(rules, QUrl("https://ads.example.com:8000/")), true); - QCOMPARE(check(rules, QUrl("http://ads.example.com.ua/foo.gif")), false); - QCOMPARE(check(rules, QUrl("http://example.com/redirect/http://ads.example.com/")), false); - // block exact address - QCOMPARE(check(rules, QUrl("http://example.com/")), true); - QCOMPARE(check(rules, QUrl("http://example.com/foo.gif")), false); - QCOMPARE(check(rules, QUrl("http://example.info/redirect/http://example.com/")), false); +TEST(AdBlockRule, ExactAddress){ + AdBlockRule *rule = parseRule_adblock("|http://example.com/|"); + EXPECT_TRUE(rule->match(QUrl("http://example.com/"))); + EXPECT_FALSE(rule->match(QUrl("http://example.com/foo.gif"))); + EXPECT_FALSE(rule->match(QUrl("http://example.info/redirect/http://example.com/"))); +} - // regular expression - QCOMPARE(check(rules, QUrl("http://another.com/banner123")), true); - QCOMPARE(check(rules, QUrl("http://another.com/banner321")), true); - QCOMPARE(check(rules, QUrl("http://another.com/banners")), false); -}*/ +TEST(AdBlockRule, RegularExpression) { + AdBlockRule *rule = parseRule_adblock("/banner\\d+/"); + EXPECT_TRUE(rule->match(QUrl("http://another.com/banner123"))); + EXPECT_TRUE(rule->match(QUrl("http://another.com/banner321"))); + EXPECT_FALSE(rule->match(QUrl("http://another.com/banners"))); +} -QTEST_GUILESS_MAIN(AdBlockTest) +int main(int argc, char **argv) { + testing::InitGoogleTest(&argc, argv); + return RUN_ALL_TESTS(); +} diff --git a/test/adblock/adblocktest.h b/test/adblock/adblocktest.h deleted file mode 100644 index 7e58197..0000000 --- a/test/adblock/adblocktest.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef ADBLOCKTEST_H -#define ADBLOCKTEST_H - -#include <QObject> - -class AdBlockTest : public QObject -{ - Q_OBJECT - -private slots: - void parseRule(); - //void parseList(); -}; - -#endif // ADBLOCKTEST_H diff --git a/test/meson.build b/test/meson.build index df6a9c9..e2e25f6 100644 --- a/test/meson.build +++ b/test/meson.build @@ -1,7 +1,9 @@ +dep_gtest = dependency('gtest') + # Adblock parsing test adblock = executable('AdblockTest', - dependencies: [dep_qt5, dep_urlfilter], - sources: ['adblock/adblocktest.cpp', qt5.preprocess(moc_headers: 'adblock/adblocktest.h', dependencies: dep_qt5)] + dependencies: [dep_gtest, dep_qt5, dep_urlfilter], + sources: ['adblock/adblocktest.cpp'] ) test('urlfilter-adblock', adblock, workdir: meson.current_source_dir()) |