diff --git a/autotests/unit/lib/advancedqueryparsertest.cpp b/autotests/unit/lib/advancedqueryparsertest.cpp --- a/autotests/unit/lib/advancedqueryparsertest.cpp +++ b/autotests/unit/lib/advancedqueryparsertest.cpp @@ -22,6 +22,7 @@ #include +Q_DECLARE_METATYPE(Baloo::Term) using namespace Baloo; class AdvancedQueryParserTest : public QObject @@ -37,6 +38,10 @@ void testDateTime(); void testOperators(); void testBinaryOperatorMissingFirstArg(); + void testNestedParentheses(); + void testNestedParentheses_data(); + void testOptimizedLogic(); + void testOptimizedLogic_data(); }; void AdvancedQueryParserTest::testSimpleProperty() @@ -199,6 +204,131 @@ QCOMPARE(term, expectedTerm); } +void AdvancedQueryParserTest::testNestedParentheses() +{ + QFETCH(QString, searchInput); + QFETCH(QString, failmessage); + QFETCH(Term, expectedTerm); + + AdvancedQueryParser parser; + const auto testTerm = parser.parse(searchInput); + qDebug() << " result term" << testTerm; + qDebug() << "expected term" << expectedTerm; + if (!failmessage.isEmpty()) { + QEXPECT_FAIL("", qPrintable(failmessage), Continue); + } + + QCOMPARE(testTerm, expectedTerm); +} + +void AdvancedQueryParserTest::testNestedParentheses_data() +{ + QTest::addColumn("searchInput"); + QTest::addColumn("expectedTerm"); + QTest::addColumn("failmessage"); + const QString nofail; + QString searchInput; + searchInput = QStringLiteral("a AND b AND c AND d"); + QTest::newRow(qPrintable(searchInput)) + << searchInput + << Term{Term::And, QList{ + Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains}, + }} + << nofail + ; + searchInput = QStringLiteral("(a AND b) AND (c OR d)"); + QTest::newRow(qPrintable(searchInput)) + << searchInput + << Term{Term::And, QList{ + Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}, + Term{Term::Or, QList{ + Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains}, + }} + }} + << nofail + ; + searchInput = QStringLiteral("(a AND (b AND (c AND d)))"); + QTest::newRow(qPrintable(searchInput)) + << searchInput + << Term{Term::And, QList{ + Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains}, + }} + << QStringLiteral("no optimization") + ; + + searchInput = QStringLiteral("(a AND (b AND (c AND d)))"); + QTest::newRow(qPrintable(searchInput)) + << searchInput + << Term{Term::And, QList{ + Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains}, + }} + << QStringLiteral("no optimization") + ; +} + +void AdvancedQueryParserTest::testOptimizedLogic() +{ + QFETCH(Term, testTerm); + QFETCH(Term, expectedTerm); + QFETCH(QString, failmessage); + qDebug() << " result term" << testTerm; + qDebug() << "expected term" << expectedTerm; + + if (!failmessage.isEmpty()) { + QEXPECT_FAIL("", qPrintable(failmessage), Continue); + } + QCOMPARE(testTerm, expectedTerm); +} + +void AdvancedQueryParserTest::testOptimizedLogic_data() +{ + QTest::addColumn("testTerm"); + QTest::addColumn("expectedTerm"); + QTest::addColumn("failmessage"); + + // a && b && c && d can be combined into one AND term with 4 subterms + QTest::addRow("&&") + << (Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains} + && Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains} + && Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains} + && Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains}) + << Term{Term::And, QList{ + Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains}, + }} + << QStringLiteral("No optimization"); + + + // (a AND b) AND (c OR d) can be merged as (a AND b AND (c OR D) + QTest::addRow("(&&) AND (||)") + << ((Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains} + && Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}) + && (Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains} + || Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains} + )) + << Term{Term::And, QList{ + Term{QStringLiteral(""), QStringLiteral("a"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("b"), Term::Contains}, + Term{Term::Or, QList{ + Term{QStringLiteral(""), QStringLiteral("c"), Term::Contains}, + Term{QStringLiteral(""), QStringLiteral("d"), Term::Contains} + }} + }} + << QStringLiteral("No optimization"); +} QTEST_MAIN(AdvancedQueryParserTest)