+++ /dev/null
-/***************************************************************************
- * Copyright (C) 2005-2018 by the Quassel Project *
- * devel@quassel-irc.org *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) version 3. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
- ***************************************************************************/
-
-#include "expressionmatchtests.h"
-
-#include <QDebug>
-#include <QString>
-#include <QStringList>
-#include <vector>
-
-#include "expressionmatch.h"
-
-void ExpressionMatchTests::runTests()
-{
- // Run all tests
- qDebug() << "Running all ExpressionMatch tests";
- runTestsEmptyPattern();
- runTestsMatchPhrase();
- runTestsMatchMultiPhrase();
- runTestsMatchWildcard();
- runTestsMatchMultiWildcard();
- runTestsMatchRegEx();
- runTestsTrimMultiWildcardWhitespace();
-
- qDebug() << "Passed all ExpressionMatch tests";
-}
-
-
-void ExpressionMatchTests::runTestsEmptyPattern()
-{
- qDebug() << "> Testing ExpressionMatch empty pattern handling";
-
- // Empty pattern
- ExpressionMatch emptyMatch =
- ExpressionMatch("", ExpressionMatch::MatchMode::MatchPhrase, false);
-
- // Assert empty
- Q_ASSERT(emptyMatch.isEmpty());
- // Assert default match fails (same as setting match empty to false)
- Q_ASSERT(!emptyMatch.match("something"));
- // Assert match empty succeeds
- Q_ASSERT(emptyMatch.match("something", true));
- // Assert empty is valid
- Q_ASSERT(emptyMatch.isValid());
-
- qDebug() << "* Passed ExpressionMatch empty pattern handling";
-}
-
-
-void ExpressionMatchTests::runTestsMatchPhrase()
-{
- qDebug() << "> Testing ExpressionMatch phrase matching";
-
- // Simple phrase, case-insensitive
- ExpressionMatch simpleMatch =
- ExpressionMatch("test", ExpressionMatch::MatchMode::MatchPhrase, false);
- // Simple phrase, case-sensitive
- ExpressionMatch simpleMatchCS =
- ExpressionMatch("test", ExpressionMatch::MatchMode::MatchPhrase, true);
- // Phrase with space, case-insensitive
- ExpressionMatch simpleMatchSpace =
- ExpressionMatch(" space ", ExpressionMatch::MatchMode::MatchPhrase, true);
- // Complex phrase
- QString complexMatchFull(R"(^(?:norm|norm\-space|\!norm\-escaped|\\\!slash\-invert|\\\\double"
- "|escape\;sep|slash\-end\-split\\|quad\\\\\!noninvert|newline\-split"
- "|newline\-split\-slash\\|slash\-at\-end\\)$)");
- ExpressionMatch complexMatch =
- ExpressionMatch(complexMatchFull, ExpressionMatch::MatchMode::MatchPhrase, false);
-
-
- // Assert valid and not empty
- Q_ASSERT(!simpleMatch.isEmpty());
- Q_ASSERT(simpleMatch.isValid());
- Q_ASSERT(!simpleMatchCS.isEmpty());
- Q_ASSERT(simpleMatchCS.isValid());
- Q_ASSERT(!simpleMatchSpace.isEmpty());
- Q_ASSERT(simpleMatchSpace.isValid());
- Q_ASSERT(!complexMatch.isEmpty());
- Q_ASSERT(complexMatch.isValid());
-
- // Assert match succeeds
- Q_ASSERT(simpleMatch.match("test"));
- Q_ASSERT(simpleMatch.match("other test;"));
- Q_ASSERT(simpleMatchSpace.match(" space "));
- // Assert partial match fails
- Q_ASSERT(!simpleMatch.match("testing"));
- Q_ASSERT(!simpleMatchSpace.match("space"));
- // Assert unrelated fails
- Q_ASSERT(!simpleMatch.match("not above"));
-
- // Assert case sensitivity followed
- Q_ASSERT(!simpleMatch.sourceCaseSensitive());
- Q_ASSERT(simpleMatch.match("TeSt"));
- Q_ASSERT(simpleMatchCS.sourceCaseSensitive());
- Q_ASSERT(!simpleMatchCS.match("TeSt"));
-
- // Assert complex phrases are escaped properly
- Q_ASSERT(complexMatch.match(complexMatchFull));
- Q_ASSERT(!complexMatch.match("norm"));
-
- qDebug() << "* Passed ExpressionMatch phrase matching";
-}
-
-
-void ExpressionMatchTests::runTestsMatchMultiPhrase()
-{
- qDebug() << "> Testing ExpressionMatch multiple phrase matching";
-
- // Simple phrases, case-insensitive
- ExpressionMatch simpleMatch =
- ExpressionMatch("test\nOther ", ExpressionMatch::MatchMode::MatchMultiPhrase, false);
- // Simple phrases, case-sensitive
- ExpressionMatch simpleMatchCS =
- ExpressionMatch("test\nOther ", ExpressionMatch::MatchMode::MatchMultiPhrase, true);
- // Complex phrases
- QString complexMatchFullA(R"(^(?:norm|norm\-space|\!norm\-escaped|\\\!slash\-invert|\\\\double)"
- R"(|escape\;sep|slash\-end\-split\\|quad\\\\\!noninvert)"
- R"(|newline\-split|newline\-split\-slash\\|slash\-at\-end\\)$)");
- QString complexMatchFullB(R"(^(?:invert|invert\-space)$)$)");
- ExpressionMatch complexMatch =
- ExpressionMatch(complexMatchFullA + "\n" + complexMatchFullB,
- ExpressionMatch::MatchMode::MatchMultiPhrase, false);
-
-
- // Assert valid and not empty
- Q_ASSERT(!simpleMatch.isEmpty());
- Q_ASSERT(simpleMatch.isValid());
- Q_ASSERT(!simpleMatchCS.isEmpty());
- Q_ASSERT(simpleMatchCS.isValid());
- Q_ASSERT(!complexMatch.isEmpty());
- Q_ASSERT(complexMatch.isValid());
-
- // Assert match succeeds
- Q_ASSERT(simpleMatch.match("test"));
- Q_ASSERT(simpleMatch.match("test[suffix]"));
- Q_ASSERT(simpleMatch.match("other test;"));
- Q_ASSERT(simpleMatch.match("Other "));
- Q_ASSERT(simpleMatch.match(".Other !"));
- // Assert partial match fails
- Q_ASSERT(!simpleMatch.match("testing"));
- Q_ASSERT(!simpleMatch.match("Other!"));
- // Assert unrelated fails
- Q_ASSERT(!simpleMatch.match("not above"));
-
- // Assert case sensitivity followed
- Q_ASSERT(!simpleMatch.sourceCaseSensitive());
- Q_ASSERT(simpleMatch.match("TeSt"));
- Q_ASSERT(simpleMatchCS.sourceCaseSensitive());
- Q_ASSERT(!simpleMatchCS.match("TeSt"));
-
- // Assert complex phrases are escaped properly
- Q_ASSERT(complexMatch.match(complexMatchFullA));
- Q_ASSERT(complexMatch.match(complexMatchFullB));
- Q_ASSERT(!complexMatch.match("norm"));
- Q_ASSERT(!complexMatch.match("invert"));
-
- qDebug() << "* Passed ExpressionMatch multiple phrase matching";
-}
-
-
-void ExpressionMatchTests::runTestsMatchWildcard()
-{
- qDebug() << "> Testing ExpressionMatch wildcard matching";
-
- // Simple wildcard, case-insensitive
- ExpressionMatch simpleMatch =
- ExpressionMatch("?test*", ExpressionMatch::MatchMode::MatchWildcard, false);
- // Simple wildcard, case-sensitive
- ExpressionMatch simpleMatchCS =
- ExpressionMatch("?test*", ExpressionMatch::MatchMode::MatchWildcard, true);
- // Escaped wildcard, case-insensitive
- ExpressionMatch simpleMatchEscape =
- ExpressionMatch(R"(\?test\*)", ExpressionMatch::MatchMode::MatchWildcard, false);
- // Inverted wildcard, case-insensitive
- ExpressionMatch simpleMatchInvert =
- ExpressionMatch("!test*", ExpressionMatch::MatchMode::MatchWildcard, false);
- // Not inverted wildcard, case-insensitive
- ExpressionMatch simpleMatchNoInvert =
- ExpressionMatch(R"(\!test*)", ExpressionMatch::MatchMode::MatchWildcard, false);
- // Not inverted wildcard literal slash, case-insensitive
- ExpressionMatch simpleMatchNoInvertSlash =
- ExpressionMatch(R"(\\!test*)", ExpressionMatch::MatchMode::MatchWildcard, false);
- // Complex wildcard
- ExpressionMatch complexMatch =
- ExpressionMatch(R"(never?gonna*give\*you\?up\\test|y\yeah\\1\\\\2\\\1inval)",
- ExpressionMatch::MatchMode::MatchWildcard, false);
-
-
- // Assert valid and not empty
- Q_ASSERT(!simpleMatch.isEmpty());
- Q_ASSERT(simpleMatch.isValid());
- Q_ASSERT(!simpleMatchCS.isEmpty());
- Q_ASSERT(simpleMatchCS.isValid());
- Q_ASSERT(!simpleMatchEscape.isEmpty());
- Q_ASSERT(simpleMatchEscape.isValid());
- Q_ASSERT(!simpleMatchInvert.isEmpty());
- Q_ASSERT(simpleMatchInvert.isValid());
- Q_ASSERT(!simpleMatchNoInvert.isEmpty());
- Q_ASSERT(simpleMatchNoInvert.isValid());
- Q_ASSERT(!simpleMatchNoInvertSlash.isEmpty());
- Q_ASSERT(simpleMatchNoInvertSlash.isValid());
- Q_ASSERT(!complexMatch.isEmpty());
- Q_ASSERT(complexMatch.isValid());
-
- // Assert match succeeds
- Q_ASSERT(simpleMatch.match("@test"));
- Q_ASSERT(simpleMatch.match("@testing"));
- Q_ASSERT(simpleMatch.match("!test"));
- Q_ASSERT(simpleMatchEscape.match("?test*"));
- Q_ASSERT(simpleMatchInvert.match("atest"));
- Q_ASSERT(simpleMatchNoInvert.match("!test"));
- Q_ASSERT(simpleMatchNoInvertSlash.match(R"(\!test)"));
- // Assert partial match fails
- Q_ASSERT(!simpleMatch.match("test"));
- // Assert unrelated fails
- Q_ASSERT(!simpleMatch.match("not above"));
- // Assert escaped wildcard fails
- Q_ASSERT(!simpleMatchEscape.match("@testing"));
- Q_ASSERT(!simpleMatchNoInvert.match("test"));
- Q_ASSERT(!simpleMatchNoInvert.match("anything"));
- Q_ASSERT(!simpleMatchNoInvertSlash.match("!test"));
- Q_ASSERT(!simpleMatchNoInvertSlash.match("test"));
- Q_ASSERT(!simpleMatchNoInvertSlash.match("anything"));
- // Assert non-inverted fails
- Q_ASSERT(!simpleMatchInvert.match("testing"));
-
- // Assert case sensitivity followed
- Q_ASSERT(!simpleMatch.sourceCaseSensitive());
- Q_ASSERT(simpleMatch.match("@TeSt"));
- Q_ASSERT(simpleMatchCS.sourceCaseSensitive());
- Q_ASSERT(!simpleMatchCS.match("@TeSt"));
-
- // Assert complex match
- Q_ASSERT(complexMatch.match(R"(neverAgonnaBBBgive*you?up\test|yyeah\1\\2\1inval)"));
- // Assert complex not literal match
- Q_ASSERT(!complexMatch.match(R"(never?gonna*give\*you\?up\\test|y\yeah\\1\\\\2\\\1inval)"));
- // Assert complex unrelated not match
- Q_ASSERT(!complexMatch.match("other"));
-
- qDebug() << "* Passed ExpressionMatch wildcard matching";
-}
-
-
-void ExpressionMatchTests::runTestsMatchMultiWildcard()
-{
- qDebug() << "> Testing ExpressionMatch multiple wildcard matching";
-
- // Simple wildcards, case-insensitive
- ExpressionMatch simpleMatch =
- ExpressionMatch("?test*;another?",
- ExpressionMatch::MatchMode::MatchMultiWildcard, false);
- // Simple wildcards, case-sensitive
- ExpressionMatch simpleMatchCS =
- ExpressionMatch("?test*;another?",
- ExpressionMatch::MatchMode::MatchMultiWildcard, true);
- // Escaped wildcards, case-insensitive
- ExpressionMatch simpleMatchEscape =
- ExpressionMatch(R"(\?test\*\;*thing\*)",
- ExpressionMatch::MatchMode::MatchMultiWildcard, false);
- // Inverted wildcards, case-insensitive
- ExpressionMatch simpleMatchInvert =
- ExpressionMatch(R"(test*;!testing)",
- ExpressionMatch::MatchMode::MatchMultiWildcard, false);
- // Implicit wildcards, case-insensitive
- ExpressionMatch simpleMatchImplicit =
- ExpressionMatch(R"(!testing*)",
- ExpressionMatch::MatchMode::MatchMultiWildcard, false);
- // Complex wildcard
- QString complexMatchFull(R"(norm;!invert; norm-space ; !invert-space ;;!;\!norm-escaped;)"
- R"(\\!slash-invert;\\\\double; escape\;sep;slash-end-split\\;)"
- R"(quad\\\\!noninvert;newline-split)""\n"
- R"(newline-split-slash\\)""\n"
- R"(slash-at-end\\)");
- // Match normal components
- QStringList complexMatchNormal = {
- R"(norm)",
- R"(norm-space)",
- R"(!norm-escaped)",
- R"(\!slash-invert)",
- R"(\\double)",
- R"(escape;sep)",
- R"(slash-end-split\)",
- R"(quad\\!noninvert)",
- R"(newline-split)",
- R"(newline-split-slash\)",
- R"(slash-at-end\)"
- };
- // Match negating components
- QStringList complexMatchInvert = {
- R"(invert)",
- R"(invert-space)"
- };
- ExpressionMatch complexMatch =
- ExpressionMatch(complexMatchFull, ExpressionMatch::MatchMode::MatchMultiWildcard,
- false);
-
-
- // Assert valid and not empty
- Q_ASSERT(!simpleMatch.isEmpty());
- Q_ASSERT(simpleMatch.isValid());
- Q_ASSERT(!simpleMatchCS.isEmpty());
- Q_ASSERT(simpleMatchCS.isValid());
- Q_ASSERT(!simpleMatchEscape.isEmpty());
- Q_ASSERT(simpleMatchEscape.isValid());
- Q_ASSERT(!simpleMatchInvert.isEmpty());
- Q_ASSERT(simpleMatchInvert.isValid());
- Q_ASSERT(!simpleMatchImplicit.isEmpty());
- Q_ASSERT(simpleMatchImplicit.isValid());
- Q_ASSERT(!complexMatch.isEmpty());
- Q_ASSERT(complexMatch.isValid());
-
- // Assert match succeeds
- Q_ASSERT(simpleMatch.match("@test"));
- Q_ASSERT(simpleMatch.match("@testing"));
- Q_ASSERT(simpleMatch.match("!test"));
- Q_ASSERT(simpleMatch.match("anotherA"));
- Q_ASSERT(simpleMatchEscape.match("?test*;thing*"));
- Q_ASSERT(simpleMatchEscape.match("?test*;AAAAAthing*"));
- Q_ASSERT(simpleMatchInvert.match("test"));
- Q_ASSERT(simpleMatchInvert.match("testing things"));
- // Assert implicit wildcard succeeds
- Q_ASSERT(simpleMatchImplicit.match("AAAAAA"));
- // Assert partial match fails
- Q_ASSERT(!simpleMatch.match("test"));
- Q_ASSERT(!simpleMatch.match("another"));
- Q_ASSERT(!simpleMatch.match("anotherBB"));
- // Assert unrelated fails
- Q_ASSERT(!simpleMatch.match("not above"));
- // Assert escaped wildcard fails
- Q_ASSERT(!simpleMatchEscape.match("@testing"));
- // Assert inverted match fails
- Q_ASSERT(!simpleMatchInvert.match("testing"));
- Q_ASSERT(!simpleMatchImplicit.match("testing"));
-
- // Assert case sensitivity followed
- Q_ASSERT(!simpleMatch.sourceCaseSensitive());
- Q_ASSERT(simpleMatch.match("@TeSt"));
- Q_ASSERT(simpleMatchCS.sourceCaseSensitive());
- Q_ASSERT(!simpleMatchCS.match("@TeSt"));
-
- // Assert complex match
- for (auto&& normMatch : complexMatchNormal) {
- // Each normal component should match
- Q_ASSERT(complexMatch.match(normMatch));
- }
-
- for (auto&& invertMatch : complexMatchInvert) {
- // Each invert component should not match
- Q_ASSERT(!complexMatch.match(invertMatch));
- }
-
- // Assert complex not literal match
- Q_ASSERT(!complexMatch.match(complexMatchFull));
- // Assert complex unrelated not match
- Q_ASSERT(!complexMatch.match("other"));
-
- qDebug() << "* Passed ExpressionMatch multiple wildcard matching";
-}
-
-
-void ExpressionMatchTests::runTestsMatchRegEx()
-{
- qDebug() << "> Testing ExpressionMatch regex matching";
-
- // Simple regex, case-insensitive
- ExpressionMatch simpleMatch =
- ExpressionMatch(R"(simple.\*escape-match.*)",
- ExpressionMatch::MatchMode::MatchRegEx, false);
- // Simple regex, case-sensitive
- ExpressionMatch simpleMatchCS =
- ExpressionMatch(R"(simple.\*escape-match.*)",
- ExpressionMatch::MatchMode::MatchRegEx, true);
- // Inverted regex, case-insensitive
- ExpressionMatch simpleMatchInvert =
- ExpressionMatch(R"(!invert.\*escape-match.*)",
- ExpressionMatch::MatchMode::MatchRegEx, false);
- // Non-inverted regex, case-insensitive
- ExpressionMatch simpleMatchNoInvert =
- ExpressionMatch(R"(\!simple.\*escape-match.*)",
- ExpressionMatch::MatchMode::MatchRegEx, false);
- // Non-inverted regex literal slash, case-insensitive
- ExpressionMatch simpleMatchNoInvertSlash =
- ExpressionMatch(R"(\\!simple.\*escape-match.*)",
- ExpressionMatch::MatchMode::MatchRegEx, false);
-
- // Assert valid and not empty
- Q_ASSERT(!simpleMatch.isEmpty());
- Q_ASSERT(simpleMatch.isValid());
- Q_ASSERT(!simpleMatchCS.isEmpty());
- Q_ASSERT(simpleMatchCS.isValid());
- Q_ASSERT(!simpleMatchInvert.isEmpty());
- Q_ASSERT(simpleMatchInvert.isValid());
- Q_ASSERT(!simpleMatchNoInvert.isEmpty());
- Q_ASSERT(simpleMatchNoInvert.isValid());
- Q_ASSERT(!simpleMatchNoInvertSlash.isEmpty());
- Q_ASSERT(simpleMatchNoInvertSlash.isValid());
-
- // Assert match succeeds
- Q_ASSERT(simpleMatch.match("simpleA*escape-match"));
- Q_ASSERT(simpleMatch.match("simpleA*escape-matchBBBB"));
- Q_ASSERT(simpleMatchInvert.match("not above"));
- Q_ASSERT(simpleMatchNoInvert.match("!simpleA*escape-matchBBBB"));
- Q_ASSERT(simpleMatchNoInvertSlash.match(R"(\!simpleA*escape-matchBBBB)"));
- // Assert partial match fails
- Q_ASSERT(!simpleMatch.match("simpleA*escape-mat"));
- Q_ASSERT(!simpleMatch.match("simple*escape-match"));
- // Assert unrelated fails
- Q_ASSERT(!simpleMatch.match("not above"));
- // Assert escaped wildcard fails
- Q_ASSERT(!simpleMatch.match("simpleABBBBescape-matchBBBB"));
- // Assert inverted fails
- Q_ASSERT(!simpleMatchInvert.match("invertA*escape-match"));
- Q_ASSERT(!simpleMatchInvert.match("invertA*escape-matchBBBB"));
- Q_ASSERT(!simpleMatchNoInvert.match("simpleA*escape-matchBBBB"));
- Q_ASSERT(!simpleMatchNoInvert.match("anything"));
- Q_ASSERT(!simpleMatchNoInvertSlash.match("!simpleA*escape-matchBBBB"));
- Q_ASSERT(!simpleMatchNoInvertSlash.match("anything"));
-
- // Assert case sensitivity followed
- Q_ASSERT(!simpleMatch.sourceCaseSensitive());
- Q_ASSERT(simpleMatch.match("SiMpLEA*escape-MATCH"));
- Q_ASSERT(simpleMatchCS.sourceCaseSensitive());
- Q_ASSERT(!simpleMatchCS.match("SiMpLEA*escape-MATCH"));
-
- qDebug() << "* Passed ExpressionMatch regex matching";
-}
-
-
-void ExpressionMatchTests::runTestsTrimMultiWildcardWhitespace()
-{
- qDebug() << "> Testing ExpressionMatch multiple wildcard whitespace trimming";
-
- // Patterns
- static constexpr uint PATTERN_SOURCE = 0;
- static constexpr uint PATTERN_RESULT = 1;
- std::vector<std::vector<QString>> patterns = {
- // Literal
- {"literal",
- "literal"},
- // Simple semicolon cleanup
- {"simple1 ;simple2; simple3 ",
- "simple1; simple2; simple3"},
- // Simple newline cleanup
- {"simple1 \nsimple2\n simple3 ",
- "simple1\nsimple2\nsimple3"},
- // Complex cleanup
- {R"(norm; norm-space ; newline-space )""\n"
- R"( ;escape \; sep ; slash-end-split\\; quad\\\\norm; newline-split-slash\\)""\n"
- R"(slash-at-end\\)",
- R"(norm; norm-space; newline-space)""\n"
- R"(escape \; sep; slash-end-split\\; quad\\\\norm; newline-split-slash\\)""\n"
- R"(slash-at-end\\)"}
- };
-
- // Check every source string...
- QString result;
- for (auto&& patternPair : patterns) {
- // Make sure data is valid
- Q_ASSERT(patternPair.size() == 2);
- // Run transformation
- result = ExpressionMatch::trimMultiWildcardWhitespace(patternPair[PATTERN_SOURCE]);
- // Assert that source trims into expected pattern
- Q_ASSERT(result == patternPair[PATTERN_RESULT]);
- // Assert that re-trimming expected pattern gives the same result
- Q_ASSERT(result == ExpressionMatch::trimMultiWildcardWhitespace(result));
- }
-
- qDebug() << "* Passed ExpressionMatch multiple wildcard whitespace trimming";
-}