blob: eec0e0bc0691178831d908cf87b32e1dc27d8445 [file] [log] [blame]
Bram Moolenaar170b10b2016-07-29 16:15:27 +02001" Tests for the undo tree.
2" Since this script is sourced we need to explicitly break changes up in
3" undo-able pieces. Do that by setting 'undolevels'.
4" Also tests :earlier and :later.
5
Bram Moolenaar3f8f8272022-12-08 21:49:35 +00006source check.vim
7source screendump.vim
8
Bram Moolenaar170b10b2016-07-29 16:15:27 +02009func Test_undotree()
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010010 new
11
12 normal! Aabc
Bram Moolenaar170b10b2016-07-29 16:15:27 +020013 set ul=100
Bram Moolenaar170b10b2016-07-29 16:15:27 +020014 let d = undotree()
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010015 call assert_equal(1, d.seq_last)
16 call assert_equal(1, d.seq_cur)
17 call assert_equal(0, d.save_last)
18 call assert_equal(0, d.save_cur)
19 call assert_equal(1, len(d.entries))
20 call assert_equal(1, d.entries[0].newhead)
21 call assert_equal(1, d.entries[0].seq)
22 call assert_true(d.entries[0].time <= d.time_cur)
23
24 normal! Adef
25 set ul=100
26 let d = undotree()
27 call assert_equal(2, d.seq_last)
28 call assert_equal(2, d.seq_cur)
29 call assert_equal(0, d.save_last)
30 call assert_equal(0, d.save_cur)
31 call assert_equal(2, len(d.entries))
32 call assert_equal(1, d.entries[0].seq)
33 call assert_equal(1, d.entries[1].newhead)
34 call assert_equal(2, d.entries[1].seq)
35 call assert_true(d.entries[1].time <= d.time_cur)
36
37 undo
38 set ul=100
39 let d = undotree()
40 call assert_equal(2, d.seq_last)
41 call assert_equal(1, d.seq_cur)
42 call assert_equal(0, d.save_last)
43 call assert_equal(0, d.save_cur)
44 call assert_equal(2, len(d.entries))
45 call assert_equal(1, d.entries[0].seq)
46 call assert_equal(1, d.entries[1].curhead)
47 call assert_equal(1, d.entries[1].newhead)
48 call assert_equal(2, d.entries[1].seq)
49 call assert_true(d.entries[1].time == d.time_cur)
50
51 normal! Aghi
52 set ul=100
53 let d = undotree()
54 call assert_equal(3, d.seq_last)
55 call assert_equal(3, d.seq_cur)
56 call assert_equal(0, d.save_last)
57 call assert_equal(0, d.save_cur)
58 call assert_equal(2, len(d.entries))
59 call assert_equal(1, d.entries[0].seq)
60 call assert_equal(2, d.entries[1].alt[0].seq)
61 call assert_equal(1, d.entries[1].newhead)
62 call assert_equal(3, d.entries[1].seq)
63 call assert_true(d.entries[1].time <= d.time_cur)
64
65 undo
66 set ul=100
67 let d = undotree()
68 call assert_equal(3, d.seq_last)
69 call assert_equal(1, d.seq_cur)
70 call assert_equal(0, d.save_last)
71 call assert_equal(0, d.save_cur)
72 call assert_equal(2, len(d.entries))
73 call assert_equal(1, d.entries[0].seq)
74 call assert_equal(2, d.entries[1].alt[0].seq)
75 call assert_equal(1, d.entries[1].curhead)
76 call assert_equal(1, d.entries[1].newhead)
77 call assert_equal(3, d.entries[1].seq)
78 call assert_true(d.entries[1].time == d.time_cur)
Bram Moolenaar170b10b2016-07-29 16:15:27 +020079
80 w! Xtest
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010081 let d = undotree()
82 call assert_equal(1, d.save_cur)
83 call assert_equal(1, d.save_last)
Bram Moolenaar170b10b2016-07-29 16:15:27 +020084 call delete('Xtest')
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010085 bwipe! Xtest
Bram Moolenaar170b10b2016-07-29 16:15:27 +020086endfunc
87
88func FillBuffer()
89 for i in range(1,13)
90 put=i
Bram Moolenaare5fa1112018-05-26 18:46:30 +020091 " Set 'undolevels' to split undo.
Bram Moolenaar170b10b2016-07-29 16:15:27 +020092 exe "setg ul=" . &g:ul
93 endfor
94endfunc
95
Devin J. Pohly5fee1112023-04-23 20:26:59 -050096func Test_undotree_bufnr()
97 new
98 let buf1 = bufnr()
99
100 normal! Aabc
101 set ul=100
102
103 " Save undo tree without bufnr as ground truth for buffer 1
104 let d1 = undotree()
105
106 new
107 let buf2 = bufnr()
108
109 normal! Adef
110 set ul=100
111
112 normal! Aghi
113 set ul=100
114
115 " Save undo tree without bufnr as ground truth for buffer 2
116 let d2 = undotree()
117
118 " Check undotree() with bufnr argument
119 let d = undotree(buf1)
120 call assert_equal(d1, d)
121 call assert_notequal(d2, d)
122
123 let d = undotree(buf2)
124 call assert_notequal(d1, d)
125 call assert_equal(d2, d)
126
127 " Switch buffers and check again
128 wincmd p
129
130 let d = undotree(buf1)
131 call assert_equal(d1, d)
132
133 let d = undotree(buf2)
134 call assert_notequal(d1, d)
135 call assert_equal(d2, d)
136
zeertzjqab9f2ec2023-08-20 18:35:10 +0200137 " error cases
138 call assert_fails('call undotree(-1)', 'E158:')
139 call assert_fails('call undotree("nosuchbuf")', 'E158:')
140
141 " after creating a buffer nosuchbuf, undotree('nosuchbuf') should
142 " not error out
143 new nosuchbuf
144 let d = {'seq_last': 0, 'entries': [], 'time_cur': 0, 'save_last': 0, 'synced': 1, 'save_cur': 0, 'seq_cur': 0}
145 call assert_equal(d, undotree("nosuchbuf"))
146 " clean up
147 bw nosuchbuf
148
Devin J. Pohly5fee1112023-04-23 20:26:59 -0500149 " Drop created windows
150 set ul&
151 new
152 only!
153endfunc
154
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200155func Test_global_local_undolevels()
156 new one
157 set undolevels=5
158 call FillBuffer()
159 " will only undo the last 5 changes, end up with 13 - (5 + 1) = 7 lines
160 earlier 10
161 call assert_equal(5, &g:undolevels)
162 call assert_equal(-123456, &l:undolevels)
163 call assert_equal('7', getline('$'))
164
165 new two
166 setlocal undolevels=2
167 call FillBuffer()
168 " will only undo the last 2 changes, end up with 13 - (2 + 1) = 10 lines
169 earlier 10
170 call assert_equal(5, &g:undolevels)
171 call assert_equal(2, &l:undolevels)
172 call assert_equal('10', getline('$'))
173
174 setlocal ul=10
175 call assert_equal(5, &g:undolevels)
176 call assert_equal(10, &l:undolevels)
177
178 " Setting local value in "two" must not change local value in "one"
179 wincmd p
180 call assert_equal(5, &g:undolevels)
181 call assert_equal(-123456, &l:undolevels)
182
183 new three
184 setglobal ul=50
185 call assert_equal(50, &g:undolevels)
186 call assert_equal(-123456, &l:undolevels)
187
Bram Moolenaar1363a302020-04-12 13:50:26 +0200188 " Resetting the local 'undolevels' value to use the global value
189 setlocal undolevels=5
190 setlocal undolevels<
191 call assert_equal(-123456, &l:undolevels)
192
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200193 " Drop created windows
194 set ul&
195 new
196 only!
197endfunc
198
199func BackOne(expected)
200 call feedkeys('g-', 'xt')
201 call assert_equal(a:expected, getline(1))
202endfunc
203
204func Test_undo_del_chars()
205 " Setup a buffer without creating undo entries
206 new
207 set ul=-1
208 call setline(1, ['123-456'])
209 set ul=100
210 1
211 call test_settime(100)
212
213 " Delete three characters and undo with g-
214 call feedkeys('x', 'xt')
215 call feedkeys('x', 'xt')
216 call feedkeys('x', 'xt')
217 call assert_equal('-456', getline(1))
218 call BackOne('3-456')
219 call BackOne('23-456')
220 call BackOne('123-456')
221 call assert_fails("BackOne('123-456')")
222
223 :" Delete three other characters and go back in time with g-
224 call feedkeys('$x', 'xt')
225 call feedkeys('x', 'xt')
226 call feedkeys('x', 'xt')
227 call assert_equal('123-', getline(1))
228 call test_settime(101)
229
230 call BackOne('123-4')
231 call BackOne('123-45')
232 " skips '123-456' because it's older
233 call BackOne('-456')
234 call BackOne('3-456')
235 call BackOne('23-456')
236 call BackOne('123-456')
237 call assert_fails("BackOne('123-456')")
238 normal 10g+
239 call assert_equal('123-', getline(1))
240
241 :" Jump two seconds and go some seconds forward and backward
242 call test_settime(103)
243 call feedkeys("Aa\<Esc>", 'xt')
244 call feedkeys("Ab\<Esc>", 'xt')
245 call feedkeys("Ac\<Esc>", 'xt')
246 call assert_equal('123-abc', getline(1))
247 earlier 1s
248 call assert_equal('123-', getline(1))
249 earlier 3s
250 call assert_equal('123-456', getline(1))
251 later 1s
252 call assert_equal('123-', getline(1))
253 later 1h
254 call assert_equal('123-abc', getline(1))
255
256 close!
257endfunc
258
Bram Moolenaarc628fdc2016-08-31 20:33:27 +0200259func Test_undolist()
260 new
261 set ul=100
262
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200263 let a = execute('undolist')
Bram Moolenaarc628fdc2016-08-31 20:33:27 +0200264 call assert_equal("\nNothing to undo", a)
265
266 " 1 leaf (2 changes).
267 call feedkeys('achange1', 'xt')
268 call feedkeys('achange2', 'xt')
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200269 let a = execute('undolist')
Bram Moolenaarc628fdc2016-08-31 20:33:27 +0200270 call assert_match("^\nnumber changes when *saved\n *2 *2 .*$", a)
271
272 " 2 leaves.
273 call feedkeys('u', 'xt')
274 call feedkeys('achange3\<Esc>', 'xt')
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200275 let a = execute('undolist')
Bram Moolenaarc628fdc2016-08-31 20:33:27 +0200276 call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a)
277 close!
278endfunc
279
280func Test_U_command()
281 new
282 set ul=100
283 call feedkeys("achange1\<Esc>", 'xt')
284 call feedkeys("achange2\<Esc>", 'xt')
285 norm! U
286 call assert_equal('', getline(1))
287 norm! U
288 call assert_equal('change1change2', getline(1))
289 close!
290endfunc
291
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200292func Test_undojoin()
293 new
294 call feedkeys("Goaaaa\<Esc>", 'xt')
295 call feedkeys("obbbb\<Esc>", 'xt')
296 call assert_equal(['aaaa', 'bbbb'], getline(2, '$'))
297 call feedkeys("u", 'xt')
298 call assert_equal(['aaaa'], getline(2, '$'))
299 call feedkeys("obbbb\<Esc>", 'xt')
300 undojoin
301 " Note: next change must not be as if typed
302 call feedkeys("occcc\<Esc>", 'x')
303 call assert_equal(['aaaa', 'bbbb', 'cccc'], getline(2, '$'))
304 call feedkeys("u", 'xt')
305 call assert_equal(['aaaa'], getline(2, '$'))
Bram Moolenaar5e4e1b12017-01-17 22:09:45 +0100306 bwipe!
307endfunc
308
309func Test_undojoin_redo()
310 new
311 call setline(1, ['first line', 'second line'])
312 call feedkeys("ixx\<Esc>", 'xt')
313 call feedkeys(":undojoin | redo\<CR>", 'xt')
314 call assert_equal('xxfirst line', getline(1))
315 call assert_equal('second line', getline(2))
316 bwipe!
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200317endfunc
318
Bram Moolenaar559b9c62019-12-15 18:09:19 +0100319" undojoin not allowed after undo
320func Test_undojoin_after_undo()
321 new
322 call feedkeys("ixx\<Esc>u", 'xt')
323 call assert_fails(':undojoin', 'E790:')
324 bwipe!
325endfunc
326
327" undojoin is a noop when no change yet, or when 'undolevels' is negative
328func Test_undojoin_noop()
329 new
330 call feedkeys(":undojoin\<CR>", 'xt')
331 call assert_equal([''], getline(1, '$'))
332 setlocal undolevels=-1
333 call feedkeys("ixx\<Esc>u", 'xt')
334 call feedkeys(":undojoin\<CR>", 'xt')
335 call assert_equal(['xx'], getline(1, '$'))
336 bwipe!
337endfunc
338
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200339func Test_undo_write()
Bram Moolenaar5842a742017-11-04 22:36:53 +0100340 call delete('Xtest')
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200341 split Xtest
342 call feedkeys("ione one one\<Esc>", 'xt')
343 w!
344 call feedkeys("otwo\<Esc>", 'xt')
345 call feedkeys("otwo\<Esc>", 'xt')
346 w
347 call feedkeys("othree\<Esc>", 'xt')
348 call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
349 earlier 1f
350 call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
351 earlier 1f
352 call assert_equal(['one one one'], getline(1, '$'))
353 earlier 1f
354 call assert_equal([''], getline(1, '$'))
355 later 1f
356 call assert_equal(['one one one'], getline(1, '$'))
357 later 1f
358 call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
359 later 1f
360 call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
361
362 close!
363 call delete('Xtest')
364 bwipe! Xtest
Bram Moolenaar9f6277b2020-02-11 22:04:02 +0100365
366 call assert_fails('earlier xyz', 'E475:')
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200367endfunc
368
369func Test_insert_expr()
370 new
371 " calling setline() triggers undo sync
372 call feedkeys("oa\<Esc>", 'xt')
373 call feedkeys("ob\<Esc>", 'xt')
374 set ul=100
375 call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
376 call assert_equal(['a', 'b', '120', '34'], getline(2, '$'))
377 call feedkeys("u", 'x')
378 call assert_equal(['a', 'b', '12'], getline(2, '$'))
379 call feedkeys("u", 'x')
380 call assert_equal(['a', 'b'], getline(2, '$'))
381
382 call feedkeys("oc\<Esc>", 'xt')
383 set ul=100
384 call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
385 call assert_equal(['a', 'b', 'c', '120', '34'], getline(2, '$'))
386 call feedkeys("u", 'x')
387 call assert_equal(['a', 'b', 'c', '12'], getline(2, '$'))
388
389 call feedkeys("od\<Esc>", 'xt')
390 set ul=100
391 call feedkeys("o1\<Esc>a2\<C-R>=string(123)\<CR>\<Esc>", 'x')
392 call assert_equal(['a', 'b', 'c', '12', 'd', '12123'], getline(2, '$'))
393 call feedkeys("u", 'x')
394 call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$'))
395
396 close!
397endfunc
Bram Moolenaarcbd4de42017-01-07 16:14:57 +0100398
399func Test_undofile_earlier()
K.Takata0500e872022-09-08 12:28:02 +0100400 if has('win32')
401 " FIXME: This test is flaky on MS-Windows.
402 let g:test_is_flaky = 1
403 endif
404
Bram Moolenaarcbd4de42017-01-07 16:14:57 +0100405 " Issue #1254
406 " create undofile with timestamps older than Vim startup time.
407 let t0 = localtime() - 43200
408 call test_settime(t0)
Bram Moolenaarcce293f2022-08-15 17:28:27 +0100409 new XfileEarlier
Bram Moolenaarcbd4de42017-01-07 16:14:57 +0100410 call feedkeys("ione\<Esc>", 'xt')
411 set ul=100
412 call test_settime(t0 + 1)
413 call feedkeys("otwo\<Esc>", 'xt')
414 set ul=100
415 call test_settime(t0 + 2)
416 call feedkeys("othree\<Esc>", 'xt')
417 set ul=100
418 w
419 wundo Xundofile
420 bwipe!
421 " restore normal timestamps.
422 call test_settime(0)
Bram Moolenaarcce293f2022-08-15 17:28:27 +0100423 new XfileEarlier
Bram Moolenaarcbd4de42017-01-07 16:14:57 +0100424 rundo Xundofile
425 earlier 1d
426 call assert_equal('', getline(1))
427 bwipe!
Bram Moolenaarcce293f2022-08-15 17:28:27 +0100428 call delete('XfileEarlier')
Bram Moolenaarcbd4de42017-01-07 16:14:57 +0100429 call delete('Xundofile')
430endfunc
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200431
Bram Moolenaar559b9c62019-12-15 18:09:19 +0100432func Test_wundo_errors()
433 new
434 call setline(1, 'hello')
435 call assert_fails('wundo! Xdoesnotexist/Xundofile', 'E828:')
436 bwipe!
437endfunc
438
439" Check that reading a truncated undo file doesn't hang.
Bram Moolenaarfb06d762019-08-04 18:55:35 +0200440func Test_undofile_truncated()
441 new
442 call setline(1, 'hello')
443 set ul=100
444 wundo Xundofile
445 let contents = readfile('Xundofile', 'B')
446
447 " try several sizes
448 for size in range(20, 500, 33)
Bram Moolenaar5b148ef2022-10-15 21:35:56 +0100449 call writefile(contents[0:size], 'Xundofile', 'D')
Bram Moolenaarfb06d762019-08-04 18:55:35 +0200450 call assert_fails('rundo Xundofile', 'E825:')
451 endfor
452
453 bwipe!
Bram Moolenaarfb06d762019-08-04 18:55:35 +0200454endfunc
455
Bram Moolenaar559b9c62019-12-15 18:09:19 +0100456func Test_rundo_errors()
457 call assert_fails('rundo XfileDoesNotExist', 'E822:')
458
Bram Moolenaar5b148ef2022-10-15 21:35:56 +0100459 call writefile(['abc'], 'Xundofile', 'D')
Bram Moolenaar559b9c62019-12-15 18:09:19 +0100460 call assert_fails('rundo Xundofile', 'E823:')
Bram Moolenaar559b9c62019-12-15 18:09:19 +0100461endfunc
462
Bram Moolenaar55b419b2020-10-04 19:56:39 +0200463func Test_undofile_next()
464 set undofile
465 new Xfoo.txt
466 execute "norm ix\<c-g>uy\<c-g>uz\<Esc>"
467 write
468 bwipe
469
470 next Xfoo.txt
471 call assert_equal('xyz', getline(1))
472 silent undo
473 call assert_equal('xy', getline(1))
474 silent undo
475 call assert_equal('x', getline(1))
476 bwipe!
477
478 call delete('Xfoo.txt')
479 call delete('.Xfoo.txt.un~')
480 set undofile&
481endfunc
482
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200483" Test for undo working properly when executing commands from a register.
484" Also test this in an empty buffer.
485func Test_cmd_in_reg_undo()
486 enew!
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200487 let @a = "Ox\<Esc>jAy\<Esc>kdd"
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200488 edit +/^$ test_undo.vim
489 normal @au
490 call assert_equal(0, &modified)
491 return
492 new
493 normal @au
494 call assert_equal(0, &modified)
495 only!
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200496 let @a = ''
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200497endfunc
Bram Moolenaar95dbcbe2018-01-27 21:01:34 +0100498
499" This used to cause an illegal memory access
500func Test_undo_append()
501 new
502 call feedkeys("axx\<Esc>v", 'xt')
503 undo
504 norm o
505 quit
506endfunc
Bram Moolenaarce46d932018-01-30 22:46:06 +0100507
508func Test_undo_0()
509 new
510 set ul=100
511 normal i1
512 undo
513 normal i2
514 undo
515 normal i3
516
517 undo 0
518 let d = undotree()
519 call assert_equal('', getline(1))
520 call assert_equal(0, d.seq_cur)
521
522 redo
523 let d = undotree()
524 call assert_equal('3', getline(1))
525 call assert_equal(3, d.seq_cur)
526
527 undo 2
528 undo 0
529 let d = undotree()
530 call assert_equal('', getline(1))
531 call assert_equal(0, d.seq_cur)
532
533 redo
534 let d = undotree()
535 call assert_equal('2', getline(1))
536 call assert_equal(2, d.seq_cur)
537
538 undo 1
539 undo 0
540 let d = undotree()
541 call assert_equal('', getline(1))
542 call assert_equal(0, d.seq_cur)
543
544 redo
545 let d = undotree()
546 call assert_equal('1', getline(1))
547 call assert_equal(1, d.seq_cur)
548
549 bwipe!
550endfunc
Bram Moolenaarf12519d2018-02-06 22:52:49 +0100551
Bram Moolenaar559b9c62019-12-15 18:09:19 +0100552" undo or redo are noop if there is nothing to undo or redo
553func Test_undo_redo_noop()
554 new
555 call assert_fails('undo 2', 'E830:')
556
557 message clear
558 undo
559 let messages = split(execute('message'), "\n")
560 call assert_equal('Already at oldest change', messages[-1])
561
562 message clear
563 redo
564 let messages = split(execute('message'), "\n")
565 call assert_equal('Already at newest change', messages[-1])
566
567 bwipe!
568endfunc
569
Bram Moolenaarf12519d2018-02-06 22:52:49 +0100570func Test_redo_empty_line()
571 new
572 exe "norm\x16r\x160"
573 exe "norm."
574 bwipe!
575endfunc
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200576
577funct Test_undofile()
578 " Test undofile() without setting 'undodir'.
579 if has('persistent_undo')
580 call assert_equal(fnamemodify('.Xundofoo.un~', ':p'), undofile('Xundofoo'))
581 else
582 call assert_equal('', undofile('Xundofoo'))
583 endif
584 call assert_equal('', undofile(''))
585
zeertzjq0df8f932024-03-07 21:40:53 +0100586 " Test undofile() with 'undodir' set to an existing directory.
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200587 call mkdir('Xundodir')
588 set undodir=Xundodir
589 let cwd = getcwd()
590 if has('win32')
591 " Replace windows drive such as C:... into C%...
Bram Moolenaar56242f22018-12-14 15:48:48 +0100592 let cwd = substitute(cwd, '^\([a-zA-Z]\):', '\1%', 'g')
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200593 endif
594 let cwd = substitute(cwd . '/Xundofoo', '/', '%', 'g')
595 if has('persistent_undo')
596 call assert_equal('Xundodir/' . cwd, undofile('Xundofoo'))
597 else
598 call assert_equal('', undofile('Xundofoo'))
599 endif
600 call assert_equal('', undofile(''))
601 call delete('Xundodir', 'd')
602
603 " Test undofile() with 'undodir' set to a non-existing directory.
Bram Moolenaarf92e58c2019-09-08 21:51:41 +0200604 call assert_equal('', 'Xundofoo'->undofile())
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200605
Bram Moolenaar077ff432019-10-28 00:42:21 +0100606 if !has('win32') && isdirectory('/tmp')
Bram Moolenaare9ebc9a2019-05-19 15:27:14 +0200607 set undodir=/tmp
Bram Moolenaar2b39d802019-05-19 16:38:56 +0200608 if has('osx')
609 call assert_equal('/tmp/%private%tmp%file', undofile('///tmp/file'))
610 else
611 call assert_equal('/tmp/%tmp%file', undofile('///tmp/file'))
612 endif
Bram Moolenaare9ebc9a2019-05-19 15:27:14 +0200613 endif
614
Bram Moolenaare5fa1112018-05-26 18:46:30 +0200615 set undodir&
616endfunc
Bram Moolenaar3e2d1c82019-12-14 20:35:01 +0100617
618" Tests for the undo file
619" Explicitly break changes up in undo-able pieces by setting 'undolevels'.
620func Test_undofile_2()
621 set undolevels=100 undofile
622 edit Xtestfile
623 call append(0, 'this is one line')
624 call cursor(1, 1)
625
626 " first a simple one-line change.
627 set undolevels=100
628 s/one/ONE/
629 set undolevels=100
630 write
631 bwipe!
632 edit Xtestfile
633 undo
634 call assert_equal('this is one line', getline(1))
635
636 " change in original file fails check
637 set noundofile
638 edit! Xtestfile
639 s/line/Line/
640 write
641 set undofile
642 bwipe!
643 edit Xtestfile
644 undo
645 call assert_equal('this is ONE Line', getline(1))
646
647 " add 10 lines, delete 6 lines, undo 3
648 set undofile
Bram Moolenaarb8bd2e62021-08-21 17:13:14 +0200649 call setbufline('%', 1, ['one', 'two', 'three', 'four', 'five', 'six',
Bram Moolenaar3e2d1c82019-12-14 20:35:01 +0100650 \ 'seven', 'eight', 'nine', 'ten'])
651 set undolevels=100
652 normal 3Gdd
653 set undolevels=100
654 normal dd
655 set undolevels=100
656 normal dd
657 set undolevels=100
658 normal dd
659 set undolevels=100
660 normal dd
661 set undolevels=100
662 normal dd
663 set undolevels=100
664 write
665 bwipe!
666 edit Xtestfile
667 normal uuu
668 call assert_equal(['one', 'two', 'six', 'seven', 'eight', 'nine', 'ten'],
669 \ getline(1, '$'))
670
671 " Test that reading the undofiles when setting undofile works
672 set noundofile undolevels=0
673 exe "normal i\n"
674 undo
675 edit! Xtestfile
676 set undofile undolevels=100
677 normal uuuuuu
678 call assert_equal(['one', 'two', 'three', 'four', 'five', 'six', 'seven',
679 \ 'eight', 'nine', 'ten'], getline(1, '$'))
680
681 bwipe!
682 call delete('Xtestfile')
683 let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
684 call delete(ufile)
685 set undofile& undolevels&
686endfunc
687
688" Test 'undofile' using a file encrypted with 'zip' crypt method
689func Test_undofile_cryptmethod_zip()
690 edit Xtestfile
691 set undofile cryptmethod=zip
692 call append(0, ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
693 call cursor(5, 1)
694
695 set undolevels=100
696 normal kkkdd
697 set undolevels=100
698 normal dd
699 set undolevels=100
700 normal dd
701 set undolevels=100
702 " encrypt the file using key 'foobar'
703 call feedkeys("foobar\nfoobar\n")
704 X
705 write!
706 bwipe!
707
708 call feedkeys("foobar\n")
709 edit Xtestfile
710 set key=
711 normal uu
712 call assert_equal(['monday', 'wednesday', 'thursday', 'friday', ''],
713 \ getline(1, '$'))
714
715 bwipe!
716 call delete('Xtestfile')
717 let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
718 call delete(ufile)
719 set undofile& undolevels& cryptmethod&
720endfunc
721
722" Test 'undofile' using a file encrypted with 'blowfish' crypt method
723func Test_undofile_cryptmethod_blowfish()
724 edit Xtestfile
725 set undofile cryptmethod=blowfish
726 call append(0, ['jan', 'feb', 'mar', 'apr', 'jun'])
727 call cursor(5, 1)
728
729 set undolevels=100
730 exe 'normal kk0ifoo '
731 set undolevels=100
732 normal dd
733 set undolevels=100
734 exe 'normal ibar '
735 set undolevels=100
736 " encrypt the file using key 'foobar'
737 call feedkeys("foobar\nfoobar\n")
738 X
739 write!
740 bwipe!
741
742 call feedkeys("foobar\n")
743 edit Xtestfile
744 set key=
745 call search('bar')
746 call assert_equal('bar apr', getline('.'))
747 undo
748 call assert_equal('apr', getline('.'))
749 undo
750 call assert_equal('foo mar', getline('.'))
751 undo
752 call assert_equal('mar', getline('.'))
753
754 bwipe!
755 call delete('Xtestfile')
756 let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
757 call delete(ufile)
758 set undofile& undolevels& cryptmethod&
759endfunc
760
761" Test 'undofile' using a file encrypted with 'blowfish2' crypt method
762func Test_undofile_cryptmethod_blowfish2()
763 edit Xtestfile
764 set undofile cryptmethod=blowfish2
765 call append(0, ['jan', 'feb', 'mar', 'apr', 'jun'])
766 call cursor(5, 1)
767
768 set undolevels=100
769 exe 'normal kk0ifoo '
770 set undolevels=100
771 normal dd
772 set undolevels=100
773 exe 'normal ibar '
774 set undolevels=100
775 " encrypt the file using key 'foo2bar'
776 call feedkeys("foo2bar\nfoo2bar\n")
777 X
778 write!
779 bwipe!
780
781 call feedkeys("foo2bar\n")
782 edit Xtestfile
783 set key=
784 call search('bar')
785 call assert_equal('bar apr', getline('.'))
786 normal u
787 call assert_equal('apr', getline('.'))
788 normal u
789 call assert_equal('foo mar', getline('.'))
790 normal u
791 call assert_equal('mar', getline('.'))
792
793 bwipe!
794 call delete('Xtestfile')
795 let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
796 call delete(ufile)
797 set undofile& undolevels& cryptmethod&
798endfunc
799
Bram Moolenaarf4fcedc2021-03-15 18:36:20 +0100800" Test for redoing with incrementing numbered registers
801func Test_redo_repeat_numbered_register()
802 new
803 for [i, v] in [[1, 'one'], [2, 'two'], [3, 'three'],
804 \ [4, 'four'], [5, 'five'], [6, 'six'],
805 \ [7, 'seven'], [8, 'eight'], [9, 'nine']]
806 exe 'let @' .. i .. '="' .. v .. '\n"'
807 endfor
808 call feedkeys('"1p.........', 'xt')
809 call assert_equal(['', 'one', 'two', 'three', 'four', 'five', 'six',
810 \ 'seven', 'eight', 'nine', 'nine'], getline(1, '$'))
811 bwipe!
812endfunc
813
Bram Moolenaar1f448d92021-03-22 19:37:06 +0100814" Test for redo in insert mode using CTRL-O with multibyte characters
815func Test_redo_multibyte_in_insert_mode()
816 new
817 call feedkeys("a\<C-K>ft", 'xt')
818 call feedkeys("uiHe\<C-O>.llo", 'xt')
819 call assert_equal("He\ufb05llo", getline(1))
820 bwipe!
821endfunc
822
LemonBoy82444ce2022-05-12 15:39:31 +0100823func Test_undo_mark()
824 new
825 " The undo is applied to the only line.
826 call setline(1, 'hello')
827 call feedkeys("ggyiw$p", 'xt')
828 undo
829 call assert_equal([0, 1, 1, 0], getpos("'["))
830 call assert_equal([0, 1, 1, 0], getpos("']"))
831 " The undo removes the last line.
832 call feedkeys("Goaaaa\<Esc>", 'xt')
833 call feedkeys("obbbb\<Esc>", 'xt')
834 undo
835 call assert_equal([0, 2, 1, 0], getpos("'["))
836 call assert_equal([0, 2, 1, 0], getpos("']"))
837 bwipe!
838endfunc
839
Bram Moolenaar3f8f8272022-12-08 21:49:35 +0000840func Test_undo_after_write()
841 " use a terminal to make undo work like when text is typed
842 CheckRunVimInTerminal
843
844 let lines =<< trim END
845 edit Xtestfile.txt
846 set undolevels=100 undofile
847 imap . <Cmd>write<CR>
848 write
849 END
850 call writefile(lines, 'Xtest_undo_after_write', 'D')
851 let buf = RunVimInTerminal('-S Xtest_undo_after_write', #{rows: 6})
852
853 call term_sendkeys(buf, "Otest.\<CR>boo!!!\<Esc>")
854 sleep 100m
855 call term_sendkeys(buf, "u")
856 call VerifyScreenDump(buf, 'Test_undo_after_write_1', {})
857
858 call term_sendkeys(buf, "u")
859 call VerifyScreenDump(buf, 'Test_undo_after_write_2', {})
860
861 call StopVimInTerminal(buf)
862 call delete('Xtestfile.txt')
Dominique Pelléb07b9dc2023-10-09 18:07:24 +0200863 call delete('.Xtestfile.txt.un~')
Bram Moolenaar3f8f8272022-12-08 21:49:35 +0000864endfunc
865
zeertzjqdccc29c2023-09-04 22:25:07 +0200866func Test_undo_range_normal()
867 new
868 call setline(1, ['asa', 'bsb'])
869 let &l:undolevels = &l:undolevels
870 %normal dfs
871 call assert_equal(['a', 'b'], getline(1, '$'))
872 undo
873 call assert_equal(['asa', 'bsb'], getline(1, '$'))
874 bwipe!
875endfunc
Bram Moolenaar3f8f8272022-12-08 21:49:35 +0000876
Bram Moolenaar3e2d1c82019-12-14 20:35:01 +0100877" vim: shiftwidth=2 sts=2 expandtab