Changeset View
Standalone View
autotests/unit/lib/advancedqueryparsertest.cpp
Show All 16 Lines | |||||
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | 17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
18 | * | 18 | * | ||
19 | */ | 19 | */ | ||
20 | 20 | | |||
21 | #include "advancedqueryparser.h" | 21 | #include "advancedqueryparser.h" | ||
22 | 22 | | |||
23 | #include <QTest> | 23 | #include <QTest> | ||
24 | 24 | | |||
25 | Q_DECLARE_METATYPE(Baloo::Term) | ||||
25 | using namespace Baloo; | 26 | using namespace Baloo; | ||
26 | 27 | | |||
27 | class AdvancedQueryParserTest : public QObject | 28 | class AdvancedQueryParserTest : public QObject | ||
28 | { | 29 | { | ||
29 | Q_OBJECT | 30 | Q_OBJECT | ||
30 | private Q_SLOTS: | 31 | private Q_SLOTS: | ||
31 | 32 | | |||
32 | void testSimpleProperty(); | 33 | void testSimpleProperty(); | ||
33 | void testSimpleString(); | 34 | void testSimpleString(); | ||
34 | void testStringAndProperty(); | 35 | void testStringAndProperty(); | ||
35 | void testLogicalOps(); | 36 | void testLogicalOps(); | ||
36 | void testNesting(); | 37 | void testNesting(); | ||
37 | void testDateTime(); | 38 | void testDateTime(); | ||
38 | void testOperators(); | 39 | void testOperators(); | ||
39 | void testBinaryOperatorMissingFirstArg(); | 40 | void testBinaryOperatorMissingFirstArg(); | ||
41 | void testNestedParentheses(); | ||||
42 | void testNestedParentheses_data(); | ||||
43 | void testOptimizedLogic(); | ||||
44 | void testOptimizedLogic_data(); | ||||
40 | }; | 45 | }; | ||
41 | 46 | | |||
42 | void AdvancedQueryParserTest::testSimpleProperty() | 47 | void AdvancedQueryParserTest::testSimpleProperty() | ||
43 | { | 48 | { | ||
44 | AdvancedQueryParser parser; | 49 | AdvancedQueryParser parser; | ||
45 | Term term = parser.parse(QStringLiteral("artist:Coldplay")); | 50 | Term term = parser.parse(QStringLiteral("artist:Coldplay")); | ||
46 | Term expectedTerm(QStringLiteral("artist"), "Coldplay"); | 51 | Term expectedTerm(QStringLiteral("artist"), "Coldplay"); | ||
47 | 52 | | |||
▲ Show 20 Lines • Show All 146 Lines • ▼ Show 20 Line(s) | |||||
194 | void AdvancedQueryParserTest::testBinaryOperatorMissingFirstArg() | 199 | void AdvancedQueryParserTest::testBinaryOperatorMissingFirstArg() | ||
195 | { | 200 | { | ||
196 | AdvancedQueryParser parser; | 201 | AdvancedQueryParser parser; | ||
197 | Term term = parser.parse(QStringLiteral("=:2")); | 202 | Term term = parser.parse(QStringLiteral("=:2")); | ||
198 | Term expectedTerm; | 203 | Term expectedTerm; | ||
199 | QCOMPARE(term, expectedTerm); | 204 | QCOMPARE(term, expectedTerm); | ||
200 | } | 205 | } | ||
201 | 206 | | |||
207 | void AdvancedQueryParserTest::testNestedParentheses() | ||||
208 | { | ||||
209 | QFETCH(QString, searchInput); | ||||
210 | QFETCH(QString, failmessage); | ||||
211 | QFETCH(Term, expectedTerm); | ||||
212 | | ||||
213 | AdvancedQueryParser parser; | ||||
214 | const auto testTerm = parser.parse(searchInput); | ||||
215 | qDebug() << " result term" << testTerm; | ||||
216 | qDebug() << "expected term" << expectedTerm; | ||||
217 | if (!failmessage.isEmpty()) { | ||||
218 | QEXPECT_FAIL("", qPrintable(failmessage), Continue); | ||||
219 | } | ||||
220 | | ||||
221 | QCOMPARE(testTerm, expectedTerm); | ||||
222 | } | ||||
223 | | ||||
224 | void AdvancedQueryParserTest::testNestedParentheses_data() | ||||
225 | { | ||||
226 | QTest::addColumn<QString>("searchInput"); | ||||
227 | QTest::addColumn<Term>("expectedTerm"); | ||||
228 | QTest::addColumn<QString>("failmessage"); | ||||
229 | | ||||
bruns: remove | |||||
230 | QTest::newRow("a AND b AND c AND d") | ||||
231 | << QStringLiteral("a AND b AND c AND d") | ||||
bruns: Remove the searchInput temporary and ... | |||||
232 | << Term{Term::And, QList<Term>{ | ||||
233 | Term{QString(), QStringLiteral("a"), Term::Contains}, | ||||
bruns: ... use the QStringLiteral here | |||||
234 | Term{QString(), QStringLiteral("b"), Term::Contains}, | ||||
235 | Term{QString(), QStringLiteral("c"), Term::Contains}, | ||||
Term{QString(), QStringLiteral("a"), Term::Contains}, see http://blog.qt.io/blog/2014/06/13/qt-weekly-13-qstringliteral/ bruns: `Term{QString(), QStringLiteral("a"), Term::Contains},`
see http://blog.qt. | |||||
236 | Term{QString(), QStringLiteral("d"), Term::Contains}, | ||||
237 | }} | ||||
238 | << QString() | ||||
239 | ; | ||||
240 | QTest::newRow("(a AND b) AND (c OR d)") | ||||
241 | << QStringLiteral("(a AND b) AND (c OR d)") | ||||
242 | << Term{Term::And, QList<Term>{ | ||||
243 | Term{QString(), QStringLiteral("a"), Term::Contains}, | ||||
244 | Term{QString(), QStringLiteral("b"), Term::Contains}, | ||||
245 | Term{Term::Or, QList<Term>{ | ||||
246 | Term{QString(), QStringLiteral("c"), Term::Contains}, | ||||
247 | Term{QString(), QStringLiteral("d"), Term::Contains}, | ||||
248 | }} | ||||
249 | }} | ||||
250 | << QString() | ||||
251 | ; | ||||
252 | QTest::newRow("(a AND (b AND (c AND d)))") | ||||
253 | << QStringLiteral("(a AND (b AND (c AND d)))") | ||||
bruns: Just `<< QString()` | |||||
254 | << Term{Term::And, QList<Term>{ | ||||
255 | Term{QString(), QStringLiteral("a"), Term::Contains}, | ||||
michaelh: What about this one? Drop it? | |||||
I think it should stay as it exercises the stack in the query parser Pseudocode: s[0] = a, AND s[1] = b, AND t = construct (c AND d) t = Term( s[1].term, t, s[1].op) t = Term( s[0].term, t, s[0].op) bruns: I think it should stay as it exercises the stack in the query parser
Pseudocode:
```
s[0] = a… | |||||
256 | Term{QString(), QStringLiteral("b"), Term::Contains}, | ||||
257 | Term{QString(), QStringLiteral("c"), Term::Contains}, | ||||
258 | Term{QString(), QStringLiteral("d"), Term::Contains}, | ||||
259 | }} | ||||
260 | << QStringLiteral("Fails to optimize for unknown reason, but output is semantically correct") | ||||
261 | ; | ||||
262 | // This test verifies that the above test is semantically correct | ||||
263 | QTest::newRow("(a AND (b AND (c AND d))) semantic") | ||||
264 | << QStringLiteral("(a AND (b AND (c AND d)))") | ||||
bruns: Adds no information, just use QString() here (and twice below) | |||||
This test fails. "no optimization" serves as a flag, that it's expected to fail and as message why. See lines 217-219. That's why I thought of dropping it, because D11826 does not make it pass. If we drop this test the failmessage column can be removed. michaelh: This test fails. "no optimization" serves as a flag, that it's expected to fail and as message… | |||||
Ah, this makes it somewhat complicated ... So the parsed query is semantically correct, only the term are not merged? Anyway, please make the message somewhat more meaningful, e.g. "Fails to optimize for unknown reason, but output is semantically correct". bruns: Ah, this makes it somewhat complicated ...
So the parsed query is semantically correct, only… | |||||
265 | << Term{Term::And, QList<Term>{ | ||||
266 | Term{QString(), QStringLiteral("a"), Term::Contains}, | ||||
267 | Term{Term::And, QList<Term>{ | ||||
268 | Term{QString(), QStringLiteral("b"), Term::Contains}, | ||||
269 | Term{Term::And, QList<Term>{ | ||||
270 | Term{QString(), QStringLiteral("c"), Term::Contains}, | ||||
271 | Term{QString(), QStringLiteral("d"), Term::Contains} | ||||
272 | | ||||
273 | }} | ||||
274 | }} | ||||
275 | }} | ||||
276 | << QString() | ||||
277 | ; | ||||
278 | | ||||
279 | } | ||||
280 | | ||||
281 | void AdvancedQueryParserTest::testOptimizedLogic() | ||||
282 | { | ||||
283 | QFETCH(Term, testTerm); | ||||
284 | QFETCH(Term, expectedTerm); | ||||
285 | qDebug() << " result term" << testTerm; | ||||
286 | qDebug() << "expected term" << expectedTerm; | ||||
287 | | ||||
288 | QEXPECT_FAIL("", "no optimization", Continue); | ||||
289 | QCOMPARE(testTerm, expectedTerm); | ||||
290 | } | ||||
bruns: Use "a && b && c && d", makes grepping in case of failure easier? | |||||
291 | | ||||
292 | void AdvancedQueryParserTest::testOptimizedLogic_data() | ||||
293 | { | ||||
294 | QTest::addColumn<Term>("testTerm"); | ||||
295 | QTest::addColumn<Term>("expectedTerm"); | ||||
296 | | ||||
297 | // a && b && c && d can be combined into one AND term with 4 subterms | ||||
298 | QTest::addRow("a && b && c && d") | ||||
299 | << (Term{QString(), QStringLiteral("a"), Term::Contains} | ||||
300 | && Term{QString(), QStringLiteral("b"), Term::Contains} | ||||
301 | && Term{QString(), QStringLiteral("c"), Term::Contains} | ||||
302 | && Term{QString(), QStringLiteral("d"), Term::Contains}) | ||||
303 | << Term{Term::And, QList<Term>{ | ||||
304 | Term{QString(), QStringLiteral("a"), Term::Contains}, | ||||
305 | Term{QString(), QStringLiteral("b"), Term::Contains}, | ||||
bruns: dito, "(a && b) && (c || d)" | |||||
306 | Term{QString(), QStringLiteral("c"), Term::Contains}, | ||||
307 | Term{QString(), QStringLiteral("d"), Term::Contains}, | ||||
308 | }} | ||||
309 | ; | ||||
310 | | ||||
311 | // (a AND b) AND (c OR d) can be merged as (a AND b AND (c OR D) | ||||
312 | QTest::addRow("(a && b) && (c || d)") | ||||
313 | << ((Term{QString(), QStringLiteral("a"), Term::Contains} | ||||
314 | && Term{QString(), QStringLiteral("b"), Term::Contains}) | ||||
315 | && (Term{QString(), QStringLiteral("c"), Term::Contains} | ||||
316 | || Term{QString(), QStringLiteral("d"), Term::Contains} | ||||
317 | )) | ||||
318 | << Term{Term::And, QList<Term>{ | ||||
319 | Term{QString(), QStringLiteral("a"), Term::Contains}, | ||||
320 | Term{QString(), QStringLiteral("b"), Term::Contains}, | ||||
321 | Term{Term::Or, QList<Term>{ | ||||
322 | Term{QString(), QStringLiteral("c"), Term::Contains}, | ||||
323 | Term{QString(), QStringLiteral("d"), Term::Contains} | ||||
324 | }} | ||||
325 | }} | ||||
326 | ; | ||||
327 | | ||||
328 | } | ||||
202 | 329 | | |||
203 | QTEST_MAIN(AdvancedQueryParserTest) | 330 | QTEST_MAIN(AdvancedQueryParserTest) | ||
204 | 331 | | |||
205 | #include "advancedqueryparsertest.moc" | 332 | #include "advancedqueryparsertest.moc" | ||
better use a different name, phrase has a special meaning, i.e. Baloo:EngineQuery:Phrase bruns: better use a different name, phrase has a special meaning, i.e. Baloo:EngineQuery:Phrase |
remove