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,128 @@ 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"); + + QTest::newRow("a AND b AND c AND d") + << QStringLiteral("a AND b AND c AND d") + << Term{Term::And, QList{ + Term{QString(), QStringLiteral("a"), Term::Contains}, + Term{QString(), QStringLiteral("b"), Term::Contains}, + Term{QString(), QStringLiteral("c"), Term::Contains}, + Term{QString(), QStringLiteral("d"), Term::Contains}, + }} + << QString() + ; + QTest::newRow("(a AND b) AND (c OR d)") + << QStringLiteral("(a AND b) AND (c OR d)") + << Term{Term::And, QList{ + Term{QString(), QStringLiteral("a"), Term::Contains}, + Term{QString(), QStringLiteral("b"), Term::Contains}, + Term{Term::Or, QList{ + Term{QString(), QStringLiteral("c"), Term::Contains}, + Term{QString(), QStringLiteral("d"), Term::Contains}, + }} + }} + << QString() + ; + QTest::newRow("(a AND (b AND (c AND d)))") + << QStringLiteral("(a AND (b AND (c AND d)))") + << Term{Term::And, QList{ + Term{QString(), QStringLiteral("a"), Term::Contains}, + Term{QString(), QStringLiteral("b"), Term::Contains}, + Term{QString(), QStringLiteral("c"), Term::Contains}, + Term{QString(), QStringLiteral("d"), Term::Contains}, + }} + << QStringLiteral("Fails to optimize for unknown reason, but output is semantically correct") + ; + // This test verifies that the above test is semantically correct + QTest::newRow("(a AND (b AND (c AND d))) semantic") + << QStringLiteral("(a AND (b AND (c AND d)))") + << Term{Term::And, QList{ + Term{QString(), QStringLiteral("a"), Term::Contains}, + Term{Term::And, QList{ + Term{QString(), QStringLiteral("b"), Term::Contains}, + Term{Term::And, QList{ + Term{QString(), QStringLiteral("c"), Term::Contains}, + Term{QString(), QStringLiteral("d"), Term::Contains} + + }} + }} + }} + << QString() + ; + +} + +void AdvancedQueryParserTest::testOptimizedLogic() +{ + QFETCH(Term, testTerm); + QFETCH(Term, expectedTerm); + qDebug() << " result term" << testTerm; + qDebug() << "expected term" << expectedTerm; + + QEXPECT_FAIL("", "no optimization", Continue); + QCOMPARE(testTerm, expectedTerm); +} + +void AdvancedQueryParserTest::testOptimizedLogic_data() +{ + QTest::addColumn("testTerm"); + QTest::addColumn("expectedTerm"); + + // a && b && c && d can be combined into one AND term with 4 subterms + QTest::addRow("a && b && c && d") + << (Term{QString(), QStringLiteral("a"), Term::Contains} + && Term{QString(), QStringLiteral("b"), Term::Contains} + && Term{QString(), QStringLiteral("c"), Term::Contains} + && Term{QString(), QStringLiteral("d"), Term::Contains}) + << Term{Term::And, QList{ + Term{QString(), QStringLiteral("a"), Term::Contains}, + Term{QString(), QStringLiteral("b"), Term::Contains}, + Term{QString(), QStringLiteral("c"), Term::Contains}, + Term{QString(), QStringLiteral("d"), Term::Contains}, + }} + ; + + // (a AND b) AND (c OR d) can be merged as (a AND b AND (c OR D) + QTest::addRow("(a && b) && (c || d)") + << ((Term{QString(), QStringLiteral("a"), Term::Contains} + && Term{QString(), QStringLiteral("b"), Term::Contains}) + && (Term{QString(), QStringLiteral("c"), Term::Contains} + || Term{QString(), QStringLiteral("d"), Term::Contains} + )) + << Term{Term::And, QList{ + Term{QString(), QStringLiteral("a"), Term::Contains}, + Term{QString(), QStringLiteral("b"), Term::Contains}, + Term{Term::Or, QList{ + Term{QString(), QStringLiteral("c"), Term::Contains}, + Term{QString(), QStringLiteral("d"), Term::Contains} + }} + }} + ; + +} QTEST_MAIN(AdvancedQueryParserTest)