blob: c1b821e4e110a1e838186469cf9540c661623352 [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
6func Test_undotree()
Bram Moolenaar80eaddd2017-11-11 23:37:08 +01007 new
8
9 normal! Aabc
Bram Moolenaar170b10b2016-07-29 16:15:27 +020010 set ul=100
Bram Moolenaar170b10b2016-07-29 16:15:27 +020011 let d = undotree()
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010012 call assert_equal(1, d.seq_last)
13 call assert_equal(1, d.seq_cur)
14 call assert_equal(0, d.save_last)
15 call assert_equal(0, d.save_cur)
16 call assert_equal(1, len(d.entries))
17 call assert_equal(1, d.entries[0].newhead)
18 call assert_equal(1, d.entries[0].seq)
19 call assert_true(d.entries[0].time <= d.time_cur)
20
21 normal! Adef
22 set ul=100
23 let d = undotree()
24 call assert_equal(2, d.seq_last)
25 call assert_equal(2, d.seq_cur)
26 call assert_equal(0, d.save_last)
27 call assert_equal(0, d.save_cur)
28 call assert_equal(2, len(d.entries))
29 call assert_equal(1, d.entries[0].seq)
30 call assert_equal(1, d.entries[1].newhead)
31 call assert_equal(2, d.entries[1].seq)
32 call assert_true(d.entries[1].time <= d.time_cur)
33
34 undo
35 set ul=100
36 let d = undotree()
37 call assert_equal(2, d.seq_last)
38 call assert_equal(1, d.seq_cur)
39 call assert_equal(0, d.save_last)
40 call assert_equal(0, d.save_cur)
41 call assert_equal(2, len(d.entries))
42 call assert_equal(1, d.entries[0].seq)
43 call assert_equal(1, d.entries[1].curhead)
44 call assert_equal(1, d.entries[1].newhead)
45 call assert_equal(2, d.entries[1].seq)
46 call assert_true(d.entries[1].time == d.time_cur)
47
48 normal! Aghi
49 set ul=100
50 let d = undotree()
51 call assert_equal(3, d.seq_last)
52 call assert_equal(3, d.seq_cur)
53 call assert_equal(0, d.save_last)
54 call assert_equal(0, d.save_cur)
55 call assert_equal(2, len(d.entries))
56 call assert_equal(1, d.entries[0].seq)
57 call assert_equal(2, d.entries[1].alt[0].seq)
58 call assert_equal(1, d.entries[1].newhead)
59 call assert_equal(3, d.entries[1].seq)
60 call assert_true(d.entries[1].time <= d.time_cur)
61
62 undo
63 set ul=100
64 let d = undotree()
65 call assert_equal(3, d.seq_last)
66 call assert_equal(1, d.seq_cur)
67 call assert_equal(0, d.save_last)
68 call assert_equal(0, d.save_cur)
69 call assert_equal(2, len(d.entries))
70 call assert_equal(1, d.entries[0].seq)
71 call assert_equal(2, d.entries[1].alt[0].seq)
72 call assert_equal(1, d.entries[1].curhead)
73 call assert_equal(1, d.entries[1].newhead)
74 call assert_equal(3, d.entries[1].seq)
75 call assert_true(d.entries[1].time == d.time_cur)
Bram Moolenaar170b10b2016-07-29 16:15:27 +020076
77 w! Xtest
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010078 let d = undotree()
79 call assert_equal(1, d.save_cur)
80 call assert_equal(1, d.save_last)
Bram Moolenaar170b10b2016-07-29 16:15:27 +020081 call delete('Xtest')
Bram Moolenaar80eaddd2017-11-11 23:37:08 +010082 bwipe! Xtest
Bram Moolenaar170b10b2016-07-29 16:15:27 +020083endfunc
84
85func FillBuffer()
86 for i in range(1,13)
87 put=i
88 " Set 'undolevels' to split undo.
89 exe "setg ul=" . &g:ul
90 endfor
91endfunc
92
93func Test_global_local_undolevels()
94 new one
95 set undolevels=5
96 call FillBuffer()
97 " will only undo the last 5 changes, end up with 13 - (5 + 1) = 7 lines
98 earlier 10
99 call assert_equal(5, &g:undolevels)
100 call assert_equal(-123456, &l:undolevels)
101 call assert_equal('7', getline('$'))
102
103 new two
104 setlocal undolevels=2
105 call FillBuffer()
106 " will only undo the last 2 changes, end up with 13 - (2 + 1) = 10 lines
107 earlier 10
108 call assert_equal(5, &g:undolevels)
109 call assert_equal(2, &l:undolevels)
110 call assert_equal('10', getline('$'))
111
112 setlocal ul=10
113 call assert_equal(5, &g:undolevels)
114 call assert_equal(10, &l:undolevels)
115
116 " Setting local value in "two" must not change local value in "one"
117 wincmd p
118 call assert_equal(5, &g:undolevels)
119 call assert_equal(-123456, &l:undolevels)
120
121 new three
122 setglobal ul=50
123 call assert_equal(50, &g:undolevels)
124 call assert_equal(-123456, &l:undolevels)
125
126 " Drop created windows
127 set ul&
128 new
129 only!
130endfunc
131
132func BackOne(expected)
133 call feedkeys('g-', 'xt')
134 call assert_equal(a:expected, getline(1))
135endfunc
136
137func Test_undo_del_chars()
138 " Setup a buffer without creating undo entries
139 new
140 set ul=-1
141 call setline(1, ['123-456'])
142 set ul=100
143 1
144 call test_settime(100)
145
146 " Delete three characters and undo with g-
147 call feedkeys('x', 'xt')
148 call feedkeys('x', 'xt')
149 call feedkeys('x', 'xt')
150 call assert_equal('-456', getline(1))
151 call BackOne('3-456')
152 call BackOne('23-456')
153 call BackOne('123-456')
154 call assert_fails("BackOne('123-456')")
155
156 :" Delete three other characters and go back in time with g-
157 call feedkeys('$x', 'xt')
158 call feedkeys('x', 'xt')
159 call feedkeys('x', 'xt')
160 call assert_equal('123-', getline(1))
161 call test_settime(101)
162
163 call BackOne('123-4')
164 call BackOne('123-45')
165 " skips '123-456' because it's older
166 call BackOne('-456')
167 call BackOne('3-456')
168 call BackOne('23-456')
169 call BackOne('123-456')
170 call assert_fails("BackOne('123-456')")
171 normal 10g+
172 call assert_equal('123-', getline(1))
173
174 :" Jump two seconds and go some seconds forward and backward
175 call test_settime(103)
176 call feedkeys("Aa\<Esc>", 'xt')
177 call feedkeys("Ab\<Esc>", 'xt')
178 call feedkeys("Ac\<Esc>", 'xt')
179 call assert_equal('123-abc', getline(1))
180 earlier 1s
181 call assert_equal('123-', getline(1))
182 earlier 3s
183 call assert_equal('123-456', getline(1))
184 later 1s
185 call assert_equal('123-', getline(1))
186 later 1h
187 call assert_equal('123-abc', getline(1))
188
189 close!
190endfunc
191
Bram Moolenaarc628fdc2016-08-31 20:33:27 +0200192func Test_undolist()
193 new
194 set ul=100
195
196 let a=execute('undolist')
197 call assert_equal("\nNothing to undo", a)
198
199 " 1 leaf (2 changes).
200 call feedkeys('achange1', 'xt')
201 call feedkeys('achange2', 'xt')
202 let a=execute('undolist')
203 call assert_match("^\nnumber changes when *saved\n *2 *2 .*$", a)
204
205 " 2 leaves.
206 call feedkeys('u', 'xt')
207 call feedkeys('achange3\<Esc>', 'xt')
208 let a=execute('undolist')
209 call assert_match("^\nnumber changes when *saved\n *2 *2 *.*\n *3 *2 .*$", a)
210 close!
211endfunc
212
213func Test_U_command()
214 new
215 set ul=100
216 call feedkeys("achange1\<Esc>", 'xt')
217 call feedkeys("achange2\<Esc>", 'xt')
218 norm! U
219 call assert_equal('', getline(1))
220 norm! U
221 call assert_equal('change1change2', getline(1))
222 close!
223endfunc
224
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200225func Test_undojoin()
226 new
227 call feedkeys("Goaaaa\<Esc>", 'xt')
228 call feedkeys("obbbb\<Esc>", 'xt')
229 call assert_equal(['aaaa', 'bbbb'], getline(2, '$'))
230 call feedkeys("u", 'xt')
231 call assert_equal(['aaaa'], getline(2, '$'))
232 call feedkeys("obbbb\<Esc>", 'xt')
233 undojoin
234 " Note: next change must not be as if typed
235 call feedkeys("occcc\<Esc>", 'x')
236 call assert_equal(['aaaa', 'bbbb', 'cccc'], getline(2, '$'))
237 call feedkeys("u", 'xt')
238 call assert_equal(['aaaa'], getline(2, '$'))
Bram Moolenaar5e4e1b12017-01-17 22:09:45 +0100239 bwipe!
240endfunc
241
242func Test_undojoin_redo()
243 new
244 call setline(1, ['first line', 'second line'])
245 call feedkeys("ixx\<Esc>", 'xt')
246 call feedkeys(":undojoin | redo\<CR>", 'xt')
247 call assert_equal('xxfirst line', getline(1))
248 call assert_equal('second line', getline(2))
249 bwipe!
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200250endfunc
251
252func Test_undo_write()
Bram Moolenaar5842a742017-11-04 22:36:53 +0100253 call delete('Xtest')
Bram Moolenaar170b10b2016-07-29 16:15:27 +0200254 split Xtest
255 call feedkeys("ione one one\<Esc>", 'xt')
256 w!
257 call feedkeys("otwo\<Esc>", 'xt')
258 call feedkeys("otwo\<Esc>", 'xt')
259 w
260 call feedkeys("othree\<Esc>", 'xt')
261 call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
262 earlier 1f
263 call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
264 earlier 1f
265 call assert_equal(['one one one'], getline(1, '$'))
266 earlier 1f
267 call assert_equal([''], getline(1, '$'))
268 later 1f
269 call assert_equal(['one one one'], getline(1, '$'))
270 later 1f
271 call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
272 later 1f
273 call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
274
275 close!
276 call delete('Xtest')
277 bwipe! Xtest
278endfunc
279
280func Test_insert_expr()
281 new
282 " calling setline() triggers undo sync
283 call feedkeys("oa\<Esc>", 'xt')
284 call feedkeys("ob\<Esc>", 'xt')
285 set ul=100
286 call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
287 call assert_equal(['a', 'b', '120', '34'], getline(2, '$'))
288 call feedkeys("u", 'x')
289 call assert_equal(['a', 'b', '12'], getline(2, '$'))
290 call feedkeys("u", 'x')
291 call assert_equal(['a', 'b'], getline(2, '$'))
292
293 call feedkeys("oc\<Esc>", 'xt')
294 set ul=100
295 call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
296 call assert_equal(['a', 'b', 'c', '120', '34'], getline(2, '$'))
297 call feedkeys("u", 'x')
298 call assert_equal(['a', 'b', 'c', '12'], getline(2, '$'))
299
300 call feedkeys("od\<Esc>", 'xt')
301 set ul=100
302 call feedkeys("o1\<Esc>a2\<C-R>=string(123)\<CR>\<Esc>", 'x')
303 call assert_equal(['a', 'b', 'c', '12', 'd', '12123'], getline(2, '$'))
304 call feedkeys("u", 'x')
305 call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$'))
306
307 close!
308endfunc
Bram Moolenaarcbd4de42017-01-07 16:14:57 +0100309
310func Test_undofile_earlier()
311 " Issue #1254
312 " create undofile with timestamps older than Vim startup time.
313 let t0 = localtime() - 43200
314 call test_settime(t0)
315 new Xfile
316 call feedkeys("ione\<Esc>", 'xt')
317 set ul=100
318 call test_settime(t0 + 1)
319 call feedkeys("otwo\<Esc>", 'xt')
320 set ul=100
321 call test_settime(t0 + 2)
322 call feedkeys("othree\<Esc>", 'xt')
323 set ul=100
324 w
325 wundo Xundofile
326 bwipe!
327 " restore normal timestamps.
328 call test_settime(0)
329 new Xfile
330 rundo Xundofile
331 earlier 1d
332 call assert_equal('', getline(1))
333 bwipe!
334 call delete('Xfile')
335 call delete('Xundofile')
336endfunc
Bram Moolenaar15993ce2017-10-26 20:21:44 +0200337
338" Test for undo working properly when executing commands from a register.
339" Also test this in an empty buffer.
340func Test_cmd_in_reg_undo()
341 enew!
342 let @a="Ox\<Esc>jAy\<Esc>kdd"
343 edit +/^$ test_undo.vim
344 normal @au
345 call assert_equal(0, &modified)
346 return
347 new
348 normal @au
349 call assert_equal(0, &modified)
350 only!
351 let @a=''
352endfunc
Bram Moolenaar95dbcbe2018-01-27 21:01:34 +0100353
354" This used to cause an illegal memory access
355func Test_undo_append()
356 new
357 call feedkeys("axx\<Esc>v", 'xt')
358 undo
359 norm o
360 quit
361endfunc
Bram Moolenaarce46d932018-01-30 22:46:06 +0100362
363func Test_undo_0()
364 new
365 set ul=100
366 normal i1
367 undo
368 normal i2
369 undo
370 normal i3
371
372 undo 0
373 let d = undotree()
374 call assert_equal('', getline(1))
375 call assert_equal(0, d.seq_cur)
376
377 redo
378 let d = undotree()
379 call assert_equal('3', getline(1))
380 call assert_equal(3, d.seq_cur)
381
382 undo 2
383 undo 0
384 let d = undotree()
385 call assert_equal('', getline(1))
386 call assert_equal(0, d.seq_cur)
387
388 redo
389 let d = undotree()
390 call assert_equal('2', getline(1))
391 call assert_equal(2, d.seq_cur)
392
393 undo 1
394 undo 0
395 let d = undotree()
396 call assert_equal('', getline(1))
397 call assert_equal(0, d.seq_cur)
398
399 redo
400 let d = undotree()
401 call assert_equal('1', getline(1))
402 call assert_equal(1, d.seq_cur)
403
404 bwipe!
405endfunc
Bram Moolenaarf12519d2018-02-06 22:52:49 +0100406
407func Test_redo_empty_line()
408 new
409 exe "norm\x16r\x160"
410 exe "norm."
411 bwipe!
412endfunc