File indexing completed on 2024-05-12 05:46:39
0001 /* 0002 Copyright (C) 2004, Arend van Beelen jr. <arend@auton.nl> 0003 Copyright (C) 2010, David Faure <faure@kde.org> 0004 0005 This file is part of the KDE project 0006 0007 This library is free software; you can redistribute it and/or 0008 modify it under the terms of the GNU Library General Public 0009 License version 2, as published by the Free Software Foundation. 0010 0011 This library is distributed in the hope that it will be useful, 0012 but WITHOUT ANY WARRANTY; without even the implied warranty of 0013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 0014 Library General Public License for more details. 0015 0016 You should have received a copy of the GNU Library General Public License 0017 along with this library; see the file COPYING.LGPL-2. If not, write to 0018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 0019 Boston, MA 02110-1301, USA. 0020 */ 0021 #include "kfindtest.h" 0022 0023 #include <QTest> 0024 0025 #include <kfind.h> 0026 0027 #include <assert.h> 0028 0029 void KFindRecorder::changeText(int line, const QString &text) 0030 { 0031 Q_ASSERT(line < m_text.count()); 0032 Q_ASSERT(m_find != nullptr); 0033 0034 m_line = line; 0035 m_text[line] = text; 0036 m_find->setData(line, text); 0037 } 0038 0039 void KFindRecorder::find(const QString &pattern, long options) 0040 { 0041 delete m_find; 0042 m_find = new KFind(pattern, options, nullptr); 0043 // Prevent dialogs from popping up 0044 m_find->closeFindNextDialog(); 0045 0046 connect(m_find, SIGNAL(highlight(QString,int,int)), 0047 SLOT(slotHighlight(QString,int,int))); 0048 connect(m_find, SIGNAL(highlight(int,int,int)), 0049 SLOT(slotHighlight(int,int,int))); 0050 0051 m_line = 0; 0052 KFind::Result result = KFind::NoMatch; 0053 do { 0054 if (options & KFind::FindIncremental) { 0055 m_find->setData(m_line, m_text[m_line]); 0056 } else { 0057 m_find->setData(m_text[m_line]); 0058 } 0059 0060 m_line++; 0061 0062 result = m_find->find(); 0063 } while (result == KFind::NoMatch && m_line < m_text.count()); 0064 } 0065 0066 bool KFindRecorder::findNext(const QString &pattern) 0067 { 0068 Q_ASSERT(m_find != nullptr); 0069 0070 if (!pattern.isNull()) { 0071 m_find->setPattern(pattern); 0072 } 0073 0074 KFind::Result result = KFind::NoMatch; 0075 do { 0076 //qDebug() << "m_line: " << m_line; 0077 0078 result = m_find->find(); 0079 0080 if (result == KFind::NoMatch && m_line < m_text.count()) { 0081 //qDebug() << "incrementing m_line..."; 0082 if (m_find->options() & KFind::FindIncremental) { 0083 m_find->setData(m_line, m_text[m_line]); 0084 } else { 0085 m_find->setData(m_text[m_line]); 0086 } 0087 0088 m_line++; 0089 } 0090 } while (result == KFind::NoMatch && m_line < m_text.count()); 0091 //qDebug() << "find next completed" << m_line; 0092 0093 return result != KFind::NoMatch; 0094 } 0095 0096 void KFindRecorder::slotHighlight(const QString &text, int index, int matchedLength) 0097 { 0098 m_hits.append(QLatin1String("line: \"") + text + QLatin1String("\", index: ") + QString::number(index) + 0099 QLatin1String(", length: ") + QString::number(matchedLength) + QLatin1Char('\n')); 0100 } 0101 0102 void KFindRecorder::slotHighlight(int id, int index, int matchedLength) 0103 { 0104 m_hits.append(QLatin1String("line: \"") + m_text[id] + QLatin1String("\", index: ") + QString::number(index) + 0105 QLatin1String(", length: ") + QString::number(matchedLength) + QLatin1Char('\n')); 0106 } 0107 0108 //// 0109 0110 TestKFind::TestKFind() 0111 : QObject() 0112 { 0113 m_text = QLatin1String("This file is part of the KDE project.\n") + 0114 QLatin1String("This library is free software; you can redistribute it and/or\n") + 0115 QLatin1String("modify it under the terms of the GNU Library General Public\n") + 0116 QLatin1String("License version 2, as published by the Free Software Foundation.\n") + 0117 QLatin1Char('\n') + 0118 QLatin1String(" This library is distributed in the hope that it will be useful,\n") + 0119 QLatin1String(" but WITHOUT ANY WARRANTY; without even the implied warranty of\n") + 0120 QLatin1String(" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\n") + 0121 QLatin1String(" Library General Public License for more details.\n") + 0122 QLatin1Char('\n') + 0123 QLatin1String(" You should have received a copy of the GNU Library General Public License\n") + 0124 QLatin1String(" along with this library; see the file COPYING.LIB. If not, write to\n") + 0125 QLatin1String(" the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n") + 0126 QLatin1String(" Boston, MA 02110-1301, USA.\n"); 0127 } 0128 0129 void TestKFind::testStaticFindString_data() 0130 { 0131 // Tests for the core method "static KFind::find" 0132 QTest::addColumn<QString>("text"); 0133 QTest::addColumn<QString>("pattern"); 0134 QTest::addColumn<int>("startIndex"); 0135 QTest::addColumn<int>("options"); 0136 QTest::addColumn<int>("expectedResult"); 0137 QTest::addColumn<int>("expectedMatchedLength"); 0138 0139 QTest::newRow("simple (0)") << "abc" << "a" << 0 << 0 << 0 << 1; 0140 QTest::newRow("simple (1)") << "abc" << "b" << 0 << 0 << 1 << 1; 0141 QTest::newRow("not found") << "abca" << "ba" << 0 << 0 << -1 << 0; 0142 QTest::newRow("from index") << "abc bc" << "b" << 3 << 0 << 4 << 1; 0143 QTest::newRow("from exact index") << "abc bc" << "b" << 4 << 0 << 4 << 1; 0144 QTest::newRow("past index (not found)") << "abc bc" << "b" << 5 << 0 << -1 << 0; 0145 QTest::newRow("dot") << "ab." << "b." << 0 << 0 << 1 << 2; 0146 QTest::newRow("^should fail") << "text" << "^tex" << 0 << 0 << -1 << 0; 0147 QTest::newRow("multiline with \\n") << "foo\nbar" << "o\nb" << 0 << 0 << 2 << 3; 0148 QTest::newRow("whole words ok") << "abc bcbc bc bmore be" << "bc" << 0 << int(KFind::WholeWordsOnly) << 9 << 2; 0149 QTest::newRow("whole words not found") << "abab abx" << "ab" << 0 << int(KFind::WholeWordsOnly) << -1 << 0; 0150 QTest::newRow("whole words not found (_)") << "abab ab_" << "ab" << 0 << int(KFind::WholeWordsOnly) << -1 << 0; 0151 QTest::newRow("whole words ok (.)") << "ab." << "ab" << 0 << int(KFind::WholeWordsOnly) << 0 << 2; 0152 QTest::newRow("backwards") << "abc bcbc8bc" << "bc" << 10 << int(KFind::FindBackwards) << 9 << 2; 0153 QTest::newRow("backwards again") << "abc bcbc8bc" << "bc" << 8 << int(KFind::FindBackwards) << 6 << 2; 0154 QTest::newRow("backwards 2") << "abc bcbc8bc" << "bc" << 5 << int(KFind::FindBackwards) << 4 << 2; 0155 QTest::newRow("backwards 3") << "abc bcbc8bc" << "bc" << 3 << int(KFind::FindBackwards) << 1 << 2; 0156 QTest::newRow("empty (0)") << "a" << "" << 0 << int(0) << 0 << 0; 0157 QTest::newRow("empty (1)") << "a" << "" << 1 << int(0) << 1 << 0; // kreplacetest testReplaceBlankSearch relies on this 0158 QTest::newRow("at end, not found") << "a" << "b" << 1 << int(0) << -1 << 0; // just for catching the while(index<text.length()) bug 0159 QTest::newRow("back, not found") << "a" << "b" << 0 << int(KFind::FindBackwards) << -1 << 0; 0160 QTest::newRow("back, at begin, found") << "a" << "a" << 0 << int(KFind::FindBackwards) << 0 << 1; 0161 QTest::newRow("back, at end, found") << "a" << "a" << 1 << int(KFind::FindBackwards) << 0 << 1; 0162 QTest::newRow("back, text shorter than pattern") << "a" << "abcd" << 0 << int(KFind::FindBackwards) << -1 << 0; 0163 } 0164 0165 void TestKFind::testStaticFindString() 0166 { 0167 // Tests for the core method "static KFind::find(text, regexp)" 0168 QFETCH(QString, text); 0169 QFETCH(QString, pattern); 0170 QFETCH(int, startIndex); 0171 QFETCH(int, options); 0172 QFETCH(int, expectedResult); 0173 QFETCH(int, expectedMatchedLength); 0174 0175 int matchedLength; 0176 const int result = KFind::find(text, pattern, startIndex, options, &matchedLength); 0177 QCOMPARE(result, expectedResult); 0178 QCOMPARE(matchedLength, expectedMatchedLength); 0179 } 0180 0181 void TestKFind::testStaticFindRegexp_data() 0182 { 0183 // Tests for the core method "static KFind::find" 0184 QTest::addColumn<QString>("text"); 0185 QTest::addColumn<QString>("pattern"); 0186 QTest::addColumn<int>("startIndex"); 0187 QTest::addColumn<int>("options"); 0188 QTest::addColumn<int>("expectedResult"); 0189 QTest::addColumn<int>("expectedMatchedLength"); 0190 0191 QTest::newRow("simple (0)") << "abc" << "a" << 0 << 0 << 0 << 1; 0192 QTest::newRow("simple (1)") << "abc" << "b" << 0 << 0 << 1 << 1; 0193 QTest::newRow("not found") << "abca" << "ba" << 0 << 0 << -1 << 0; 0194 QTest::newRow("from index") << "abc bc" << "b" << 3 << 0 << 4 << 1; 0195 QTest::newRow("from exact index") << "abc bc" << "b" << 4 << 0 << 4 << 1; 0196 QTest::newRow("past index (not found)") << "abc bc" << "b" << 5 << 0 << -1 << 0; 0197 QTest::newRow("dot") << "abc" << "b." << 0 << 0 << 1 << 2; 0198 QTest::newRow("^simple") << "text" << "^tex" << 0 << 0 << 0 << 3; 0199 QTest::newRow("^multiline first") << "foo\nbar" << "^f" << 0 << 0 << 0 << 1; 0200 QTest::newRow("^multiline last") << "foo\nbar" << "^bar" << 0 << 0 << 4 << 3; 0201 QTest::newRow("^multiline with index") << "boo\nbar" << "^b" << 1 << 0 << 4 << 1; 0202 QTest::newRow("simple$") << "text" << "xt$" << 0 << 0 << 2 << 2; 0203 QTest::newRow("$ backwards") << "text" << "xt$" << 4 << int(KFind::FindBackwards) << 2 << 2; 0204 QTest::newRow("multiline$") << "foo\nbar" << "oo$" << 0 << 0 << 1 << 2; 0205 QTest::newRow("multiline$ intermediary line") << "foo\nbar\nagain bar" << "r$" << 0 << 0 << 6 << 1; 0206 QTest::newRow("multiline$ with index, last line") << "foo\nbar\nagain bar" << "r$" << 7 << 0 << 16 << 1; 0207 QTest::newRow("multiline$ backwards") << "foo\nbar" << "oo$" << 7 << int(KFind::FindBackwards) << 1 << 2; 0208 QTest::newRow("multiline with \\n") << "foo\nbar" << "o\nb" << 0 << 0 << 2 << 3; 0209 QTest::newRow("whole words ok") << "abc bcbc bc bmore be" << "b." << 0 << int(KFind::WholeWordsOnly) << 9 << 2; 0210 QTest::newRow("whole words not found") << "abab abx" << "ab" << 0 << int(KFind::WholeWordsOnly) << -1 << 0; 0211 QTest::newRow("whole words not found (_)") << "abab ab_" << "ab" << 0 << int(KFind::WholeWordsOnly) << -1 << 0; 0212 QTest::newRow("whole words ok (.)") << "ab." << "ab" << 0 << int(KFind::WholeWordsOnly) << 0 << 2; 0213 QTest::newRow("backwards") << "abc bcbc bc" << "b." << 10 << int(KFind::FindBackwards) << 9 << 2; 0214 QTest::newRow("empty (0)") << "a" << "" << 0 << int(0) << 0 << 0; 0215 QTest::newRow("empty (1)") << "a" << "" << 1 << int(0) << 1 << 0; // kreplacetest testReplaceBlankSearch relies on this 0216 QTest::newRow("at end, not found") << "a" << "b" << 1 << int(0) << -1 << 0; // just for catching the while(index<text.length()) bug 0217 QTest::newRow("back, not found") << "a" << "b" << 0 << int(KFind::FindBackwards) << -1 << 0; 0218 QTest::newRow("back, at begin, found") << "a" << "a" << 0 << int(KFind::FindBackwards) << 0 << 1; 0219 QTest::newRow("back, at end, found") << "a" << "a" << 1 << int(KFind::FindBackwards) << 0 << 1; 0220 QTest::newRow("back, text shorter than pattern") << "a" << "abcd" << 0 << int(KFind::FindBackwards) << -1 << 0; 0221 } 0222 0223 void TestKFind::testStaticFindRegexp() 0224 { 0225 // Tests for the core method "static KFind::find(text, regexp)" 0226 QFETCH(QString, text); 0227 QFETCH(QString, pattern); 0228 QFETCH(int, startIndex); 0229 QFETCH(int, options); 0230 QFETCH(int, expectedResult); 0231 QFETCH(int, expectedMatchedLength); 0232 0233 int matchedLength; 0234 const int result = KFind::find(text, QRegExp(pattern), startIndex, options, &matchedLength); 0235 QCOMPARE(result, expectedResult); 0236 QCOMPARE(matchedLength, expectedMatchedLength); 0237 } 0238 0239 void TestKFind::testSimpleSearch() 0240 { 0241 // first we do a simple text searching the text and doing a few find nexts 0242 KFindRecorder test(m_text.split(QLatin1Char('\n'))); 0243 test.find(QStringLiteral("This"), 0); 0244 while (test.findNext()) {} 0245 0246 const QString output1 = 0247 QLatin1String("line: \"This file is part of the KDE project.\", index: 0, length: 4\n") + 0248 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 0, length: 4\n") + 0249 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 4, length: 4\n") + 0250 QLatin1String("line: \" along with this library; see the file COPYING.LIB. If not, write to\", index: 15, length: 4\n"); 0251 0252 QCOMPARE(test.hits().join(QString()), output1); 0253 } 0254 0255 void TestKFind::testSimpleRegexp() 0256 { 0257 KFindRecorder test(m_text.split(QLatin1Char('\n'))); 0258 test.find(QStringLiteral("W.R+ANT[YZ]"), KFind::RegularExpression | KFind::CaseSensitive); 0259 while (test.findNext()) {} 0260 const QString output = 0261 QStringLiteral("line: \" but WITHOUT ANY WARRANTY; without even the implied warranty of\", index: 20, length: 8\n"); 0262 QCOMPARE(test.hits().join(QString()), output); 0263 } 0264 0265 void TestKFind::testLineBeginRegexp() 0266 { 0267 // Let's see what QRegExp can do on a big text (like in KTextEdit) 0268 { 0269 const QString foobar = QStringLiteral("foo\nbar"); 0270 const int idx = foobar.indexOf(QRegExp(QStringLiteral("^bar"))); 0271 QCOMPARE(idx, -1); // it doesn't find it. No /m support, as they say. Too bad. 0272 } 0273 0274 // If we split, it works, but then looking for "foo\nbar" won't work... 0275 KFindRecorder test(m_text.split(QLatin1Char('\n'))); 0276 test.find(QStringLiteral("^License"), KFind::RegularExpression); 0277 while (test.findNext()) {} 0278 const QString output = 0279 QStringLiteral("line: \"License version 2, as published by the Free Software Foundation.\", index: 0, length: 7\n"); 0280 QCOMPARE(test.hits().join(QString()), output); 0281 } 0282 0283 void TestKFind::testFindIncremental() 0284 { 0285 // FindIncremental with static contents... 0286 0287 KFindRecorder test(m_text.split(QLatin1Char('\n'))); 0288 test.find(QString(), KFind::FindIncremental); 0289 test.findNext(QStringLiteral("i")); 0290 test.findNext(QStringLiteral("is")); 0291 test.findNext(QStringLiteral("ist")); 0292 test.findNext(); 0293 test.findNext(QStringLiteral("istri")); 0294 test.findNext(QStringLiteral("istr")); 0295 test.findNext(QStringLiteral("ist")); 0296 test.findNext(QStringLiteral("is")); 0297 test.findNext(QStringLiteral("W")); 0298 test.findNext(QStringLiteral("WA")); 0299 test.findNext(QStringLiteral("WARRANTY")); 0300 test.findNext(QStringLiteral("Free")); 0301 test.findNext(QStringLiteral("Software Foundation")); 0302 0303 const QString output2 = 0304 QLatin1String("line: \"This file is part of the KDE project.\", index: 0, length: 0\n") + 0305 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 1\n") + 0306 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 2\n") + 0307 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 42, length: 3\n") + 0308 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 3\n") + 0309 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 5\n") + 0310 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 4\n") + 0311 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 3\n") + 0312 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 2\n") + 0313 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 25, length: 1\n") + 0314 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 25, length: 2\n") + 0315 QLatin1String("line: \" but WITHOUT ANY WARRANTY; without even the implied warranty of\", index: 20, length: 8\n") + 0316 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 16, length: 4\n") + 0317 QLatin1String("line: \"License version 2, as published by the Free Software Foundation.\", index: 44, length: 19\n"); 0318 0319 QCOMPARE(test.hits().join(QString()), output2); 0320 } 0321 0322 void TestKFind::testFindIncrementalDynamic() 0323 { 0324 // Now do that again but with pages that change between searches 0325 KFindRecorder test(m_text.split(QLatin1Char('\n'))); 0326 0327 test.find(QString(), KFind::FindIncremental); 0328 test.findNext(QStringLiteral("i")); 0329 test.findNext(QStringLiteral("is")); 0330 test.findNext(QStringLiteral("ist")); 0331 test.findNext(QStringLiteral("istr")); 0332 test.findNext(); 0333 test.changeText(1, QStringLiteral("The second line now looks a whole lot different.")); 0334 test.findNext(QStringLiteral("istri")); 0335 test.findNext(QStringLiteral("istr")); 0336 test.findNext(QStringLiteral("ist")); 0337 test.findNext(QStringLiteral("is")); 0338 test.findNext(QStringLiteral("i")); 0339 test.findNext(QStringLiteral("W")); 0340 test.findNext(QStringLiteral("WA")); 0341 test.findNext(QStringLiteral("WARRANTY")); 0342 test.changeText(6, QStringLiteral(" but WITHOUT ANY xxxx; without even the implied warranty of")); 0343 test.findNext(QStringLiteral("WARRAN")); 0344 test.findNext(QStringLiteral("Free")); 0345 test.findNext(QStringLiteral("Software Foundation")); 0346 0347 const QString output3 = 0348 QLatin1String("line: \"This file is part of the KDE project.\", index: 0, length: 0\n") + 0349 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 1\n") + 0350 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 2\n") + 0351 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 42, length: 3\n") + 0352 QLatin1String("line: \"This library is free software; you can redistribute it and/or\", index: 42, length: 4\n") + 0353 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 4\n") + 0354 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 5\n") + 0355 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 4\n") + 0356 QLatin1String("line: \" This library is distributed in the hope that it will be useful,\", index: 21, length: 3\n") + 0357 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 2\n") + 0358 QLatin1String("line: \"This file is part of the KDE project.\", index: 2, length: 1\n") + 0359 QLatin1String("line: \"The second line now looks a whole lot different.\", index: 18, length: 1\n") + 0360 QLatin1String("line: \"License version 2, as published by the Free Software Foundation.\", index: 48, length: 2\n") + 0361 QLatin1String("line: \" but WITHOUT ANY WARRANTY; without even the implied warranty of\", index: 20, length: 8\n") + 0362 QLatin1String("line: \" but WITHOUT ANY xxxx; without even the implied warranty of\", index: 51, length: 6\n") + 0363 QLatin1String("line: \"License version 2, as published by the Free Software Foundation.\", index: 39, length: 4\n") + 0364 QLatin1String("line: \"License version 2, as published by the Free Software Foundation.\", index: 44, length: 19\n"); 0365 0366 QCOMPARE(test.hits().join(QString()), output3); 0367 } 0368 0369 QTEST_MAIN(TestKFind) 0370