File indexing completed on 2024-09-15 12:02:35
0001 /* 0002 This file is part of the KDE libraries 0003 SPDX-FileCopyrightText: 2010-2018 Dominik Haumann <dhaumann@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "movingcursor_test.h" 0009 #include "moc_movingcursor_test.cpp" 0010 0011 #include <katedocument.h> 0012 #include <kateglobal.h> 0013 #include <ktexteditor/movingcursor.h> 0014 0015 #include <QtTestWidgets> 0016 0017 using namespace KTextEditor; 0018 0019 QTEST_MAIN(MovingCursorTest) 0020 0021 MovingCursorTest::MovingCursorTest() 0022 : QObject() 0023 { 0024 KTextEditor::EditorPrivate::enableUnitTestMode(); 0025 } 0026 0027 MovingCursorTest::~MovingCursorTest() 0028 { 0029 } 0030 0031 // tests: 0032 // - MovingCursor with StayOnInsert 0033 // - MovingCursor with MoveOnInsert 0034 void MovingCursorTest::testMovingCursor() 0035 { 0036 KTextEditor::DocumentPrivate doc; 0037 MovingCursor *invalid = doc.newMovingCursor(Cursor::invalid()); 0038 MovingCursor *moveOnInsert = doc.newMovingCursor(Cursor(0, 0), MovingCursor::MoveOnInsert); 0039 MovingCursor *stayOnInsert = doc.newMovingCursor(Cursor(0, 0), MovingCursor::StayOnInsert); 0040 0041 // verify initial conditions 0042 QVERIFY(!invalid->isValid()); 0043 QCOMPARE(moveOnInsert->toCursor(), Cursor(0, 0)); 0044 QCOMPARE(stayOnInsert->toCursor(), Cursor(0, 0)); 0045 0046 // insert some text 0047 doc.insertText(Cursor(0, 0), 0048 "\n" 0049 "1\n" 0050 "22"); 0051 0052 // check new cursor positions 0053 QCOMPARE(moveOnInsert->toCursor(), Cursor(2, 2)); 0054 QCOMPARE(stayOnInsert->toCursor(), Cursor(0, 0)); 0055 0056 // set position to (1, 1) and insert text before cursor 0057 stayOnInsert->setPosition(Cursor(1, 1)); 0058 QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); 0059 doc.insertText(Cursor(1, 0), "test"); 0060 QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 5)); 0061 doc.undo(); 0062 QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); 0063 0064 // position still at (1, 1). insert text at cursor 0065 doc.insertText(Cursor(1, 1), "test"); 0066 QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); 0067 doc.undo(); 0068 QCOMPARE(stayOnInsert->toCursor(), Cursor(1, 1)); 0069 0070 // 0071 // same tests with the moveOnInsert cursor 0072 // 0073 // set position to (1, 1) and insert text before cursor 0074 moveOnInsert->setPosition(Cursor(1, 1)); 0075 QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 1)); 0076 doc.insertText(Cursor(1, 0), "test"); 0077 QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 5)); 0078 doc.undo(); 0079 QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 1)); 0080 0081 // position still at (1, 1). insert text at cursor 0082 doc.insertText(Cursor(1, 1), "test"); 0083 QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 5)); 0084 doc.undo(); 0085 QCOMPARE(moveOnInsert->toCursor(), Cursor(1, 1)); 0086 0087 // set both cursors to (2, 1) then delete text range that contains cursors 0088 moveOnInsert->setPosition(Cursor(2, 1)); 0089 stayOnInsert->setPosition(Cursor(2, 1)); 0090 doc.removeText(Range(Cursor(2, 0), Cursor(2, 2))); 0091 QCOMPARE(moveOnInsert->toCursor(), Cursor(2, 0)); 0092 QCOMPARE(moveOnInsert->toCursor(), Cursor(2, 0)); 0093 } 0094 0095 // tests: 0096 // - atStartOfDocument 0097 // - atStartOfLine 0098 // - atEndOfDocument 0099 // - atEndOfLine 0100 // - move forward with Wrap 0101 // - move forward with NoWrap 0102 // - move backward 0103 // - gotoNextLine 0104 // - gotoPreviousLine 0105 void MovingCursorTest::testConvenienceApi() 0106 { 0107 KTextEditor::DocumentPrivate doc; 0108 doc.setText( 0109 "\n" 0110 "1\n" 0111 "22\n" 0112 "333\n" 0113 "4444\n" 0114 "55555"); 0115 0116 // check start and end of document 0117 MovingCursor *startOfDoc = doc.newMovingCursor(Cursor(0, 0)); 0118 MovingCursor *endOfDoc = doc.newMovingCursor(Cursor(5, 5)); 0119 QVERIFY(startOfDoc->atStartOfDocument()); 0120 QVERIFY(startOfDoc->atStartOfLine()); 0121 QVERIFY(endOfDoc->atEndOfDocument()); 0122 QVERIFY(endOfDoc->atEndOfLine()); 0123 0124 // set cursor to (2, 2) and then move to the left two times 0125 MovingCursor *moving = doc.newMovingCursor(Cursor(2, 2)); 0126 QVERIFY(moving->atEndOfLine()); // at 2, 2 0127 QVERIFY(moving->move(-1)); // at 2, 1 0128 QCOMPARE(moving->toCursor(), Cursor(2, 1)); 0129 QVERIFY(!moving->atEndOfLine()); 0130 QVERIFY(moving->move(-1)); // at 2, 0 0131 QCOMPARE(moving->toCursor(), Cursor(2, 0)); 0132 QVERIFY(moving->atStartOfLine()); 0133 0134 // now move again to the left, should wrap to (1, 1) 0135 QVERIFY(moving->move(-1)); // at 1, 1 0136 QCOMPARE(moving->toCursor(), Cursor(1, 1)); 0137 QVERIFY(moving->atEndOfLine()); 0138 0139 // advance 7 characters to position (3, 3) 0140 QVERIFY(moving->move(7)); // at 3, 3 0141 QCOMPARE(moving->toCursor(), Cursor(3, 3)); 0142 0143 // advance 20 characters in NoWrap mode, then go back 10 characters 0144 QVERIFY(moving->move(20, MovingCursor::NoWrap)); // at 3, 23 0145 QCOMPARE(moving->toCursor(), Cursor(3, 23)); 0146 QVERIFY(moving->move(-10)); // at 3, 13 0147 QCOMPARE(moving->toCursor(), Cursor(3, 13)); 0148 0149 // still at invalid text position. move one char to wrap around 0150 QVERIFY(!moving->isValidTextPosition()); // at 3, 13 0151 QVERIFY(moving->move(1)); // at 4, 0 0152 QCOMPARE(moving->toCursor(), Cursor(4, 0)); 0153 0154 // moving 11 characters in wrap mode moves to (5, 6), which is not a valid 0155 // text position anymore. Hence, moving should be rejected. 0156 QVERIFY(!moving->move(11)); 0157 QVERIFY(moving->move(10)); 0158 QVERIFY(moving->atEndOfDocument()); 0159 0160 // try to move to next line, which fails. then go to previous line 0161 QVERIFY(!moving->gotoNextLine()); 0162 QVERIFY(moving->gotoPreviousLine()); 0163 QCOMPARE(moving->toCursor(), Cursor(4, 0)); 0164 } 0165 0166 void MovingCursorTest::testOperators() 0167 { 0168 KTextEditor::DocumentPrivate doc; 0169 doc.setText( 0170 "--oo--\n" 0171 "--oo--\n" 0172 "--oo--"); 0173 0174 // create lots of cursors for comparison 0175 Cursor invalid = Cursor::invalid(); 0176 Cursor c02(0, 2); 0177 Cursor c04(0, 4); 0178 Cursor c14(1, 4); 0179 0180 MovingCursor *m02 = doc.newMovingCursor(Cursor(0, 2)); 0181 MovingCursor *m04 = doc.newMovingCursor(Cursor(0, 4)); 0182 MovingCursor *m14 = doc.newMovingCursor(Cursor(1, 4)); 0183 0184 // invalid comparison 0185 QVERIFY(invalid == invalid); 0186 QVERIFY(invalid <= c02); 0187 QVERIFY(invalid < c02); 0188 QVERIFY(!(invalid > c02)); 0189 QVERIFY(!(invalid >= c02)); 0190 0191 QVERIFY(!(invalid == *m02)); 0192 QVERIFY(invalid <= *m02); 0193 QVERIFY(invalid < *m02); 0194 QVERIFY(!(invalid > *m02)); 0195 QVERIFY(!(invalid >= *m02)); 0196 0197 QVERIFY(!(*m02 == invalid)); 0198 QVERIFY(!(*m02 <= invalid)); 0199 QVERIFY(!(*m02 < invalid)); 0200 QVERIFY(*m02 > invalid); 0201 QVERIFY(*m02 >= invalid); 0202 0203 // MovingCursor <-> MovingCursor 0204 QVERIFY(*m02 == *m02); 0205 QVERIFY(*m02 <= *m02); 0206 QVERIFY(*m02 >= *m02); 0207 QVERIFY(!(*m02 < *m02)); 0208 QVERIFY(!(*m02 > *m02)); 0209 QVERIFY(!(*m02 != *m02)); 0210 0211 QVERIFY(!(*m02 == *m04)); 0212 QVERIFY(*m02 <= *m04); 0213 QVERIFY(!(*m02 >= *m04)); 0214 QVERIFY(*m02 < *m04); 0215 QVERIFY(!(*m02 > *m04)); 0216 QVERIFY(*m02 != *m04); 0217 0218 QVERIFY(!(*m04 == *m02)); 0219 QVERIFY(!(*m04 <= *m02)); 0220 QVERIFY(*m04 >= *m02); 0221 QVERIFY(!(*m04 < *m02)); 0222 QVERIFY(*m04 > *m02); 0223 QVERIFY(*m04 != *m02); 0224 0225 QVERIFY(!(*m02 == *m14)); 0226 QVERIFY(*m02 <= *m14); 0227 QVERIFY(!(*m02 >= *m14)); 0228 QVERIFY(*m02 < *m14); 0229 QVERIFY(!(*m02 > *m14)); 0230 QVERIFY(*m02 != *m14); 0231 0232 QVERIFY(!(*m14 == *m02)); 0233 QVERIFY(!(*m14 <= *m02)); 0234 QVERIFY(*m14 >= *m02); 0235 QVERIFY(!(*m14 < *m02)); 0236 QVERIFY(*m14 > *m02); 0237 QVERIFY(*m14 != *m02); 0238 0239 // MovingCursor <-> Cursor 0240 QVERIFY(*m02 == c02); 0241 QVERIFY(*m02 <= c02); 0242 QVERIFY(*m02 >= c02); 0243 QVERIFY(!(*m02 < c02)); 0244 QVERIFY(!(*m02 > c02)); 0245 QVERIFY(!(*m02 != c02)); 0246 0247 QVERIFY(!(*m02 == c04)); 0248 QVERIFY(*m02 <= c04); 0249 QVERIFY(!(*m02 >= c04)); 0250 QVERIFY(*m02 < c04); 0251 QVERIFY(!(*m02 > c04)); 0252 QVERIFY(*m02 != c04); 0253 0254 QVERIFY(!(*m04 == c02)); 0255 QVERIFY(!(*m04 <= c02)); 0256 QVERIFY(*m04 >= c02); 0257 QVERIFY(!(*m04 < c02)); 0258 QVERIFY(*m04 > c02); 0259 QVERIFY(*m04 != c02); 0260 0261 QVERIFY(!(*m02 == c14)); 0262 QVERIFY(*m02 <= c14); 0263 QVERIFY(!(*m02 >= c14)); 0264 QVERIFY(*m02 < c14); 0265 QVERIFY(!(*m02 > c14)); 0266 QVERIFY(*m02 != c14); 0267 0268 QVERIFY(!(*m14 == c02)); 0269 QVERIFY(!(*m14 <= c02)); 0270 QVERIFY(*m14 >= c02); 0271 QVERIFY(!(*m14 < c02)); 0272 QVERIFY(*m14 > c02); 0273 QVERIFY(*m14 != c02); 0274 0275 // Cursor <-> MovingCursor 0276 QVERIFY(c02 == *m02); 0277 QVERIFY(c02 <= *m02); 0278 QVERIFY(c02 >= *m02); 0279 QVERIFY(!(c02 < *m02)); 0280 QVERIFY(!(c02 > *m02)); 0281 QVERIFY(!(c02 != *m02)); 0282 0283 QVERIFY(!(c02 == *m04)); 0284 QVERIFY(c02 <= *m04); 0285 QVERIFY(!(c02 >= *m04)); 0286 QVERIFY(c02 < *m04); 0287 QVERIFY(!(c02 > *m04)); 0288 QVERIFY(c02 != *m04); 0289 0290 QVERIFY(!(c04 == *m02)); 0291 QVERIFY(!(c04 <= *m02)); 0292 QVERIFY(c04 >= *m02); 0293 QVERIFY(!(c04 < *m02)); 0294 QVERIFY(c04 > *m02); 0295 QVERIFY(c04 != *m02); 0296 0297 QVERIFY(!(c02 == *m14)); 0298 QVERIFY(c02 <= *m14); 0299 QVERIFY(!(c02 >= *m14)); 0300 QVERIFY(c02 < *m14); 0301 QVERIFY(!(c02 > *m14)); 0302 QVERIFY(c02 != *m14); 0303 0304 QVERIFY(!(c14 == *m02)); 0305 QVERIFY(!(c14 <= *m02)); 0306 QVERIFY(c14 >= *m02); 0307 QVERIFY(!(c14 < *m02)); 0308 QVERIFY(c14 > *m02); 0309 QVERIFY(c14 != *m02); 0310 } 0311 0312 void MovingCursorTest::testInvalidMovingCursor() 0313 { 0314 KTextEditor::DocumentPrivate *doc = new KTextEditor::DocumentPrivate; 0315 0316 // add invalid MovingCursor. Inserts c into KateBuffer::m_invalidCursors 0317 MovingCursor *c = doc->newMovingCursor(Cursor(-1, -1)); 0318 QVERIFY(Cursor(-1, -1) == *c); 0319 0320 c->setPosition(Cursor(0, 0)); 0321 QVERIFY(Cursor(0, 0) == *c); 0322 0323 // now c should be removed from KateBuffer::m_invalidCursors 0324 delete c; 0325 0326 // crash in bug https://bugs.kde.org/show_bug.cgi?id=248926 0327 // if it crashes: c is still in KateBuffer::m_invalidCursors -> double deletion 0328 delete doc; 0329 }