xref: /vim-8.2.3635/src/testdir/test_undo.vim (revision 125ed274)
1" 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()
7  new
8
9  normal! Aabc
10  set ul=100
11  let d = undotree()
12  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)
76
77  w! Xtest
78  let d = undotree()
79  call assert_equal(1, d.save_cur)
80  call assert_equal(1, d.save_last)
81  call delete('Xtest')
82  bwipe! Xtest
83endfunc
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  " Resetting the local 'undolevels' value to use the global value
127  setlocal undolevels=5
128  setlocal undolevels<
129  call assert_equal(-123456, &l:undolevels)
130
131  " Drop created windows
132  set ul&
133  new
134  only!
135endfunc
136
137func BackOne(expected)
138  call feedkeys('g-', 'xt')
139  call assert_equal(a:expected, getline(1))
140endfunc
141
142func Test_undo_del_chars()
143  " Setup a buffer without creating undo entries
144  new
145  set ul=-1
146  call setline(1, ['123-456'])
147  set ul=100
148  1
149  call test_settime(100)
150
151  " Delete three characters and undo with g-
152  call feedkeys('x', 'xt')
153  call feedkeys('x', 'xt')
154  call feedkeys('x', 'xt')
155  call assert_equal('-456', getline(1))
156  call BackOne('3-456')
157  call BackOne('23-456')
158  call BackOne('123-456')
159  call assert_fails("BackOne('123-456')")
160
161  :" Delete three other characters and go back in time with g-
162  call feedkeys('$x', 'xt')
163  call feedkeys('x', 'xt')
164  call feedkeys('x', 'xt')
165  call assert_equal('123-', getline(1))
166  call test_settime(101)
167
168  call BackOne('123-4')
169  call BackOne('123-45')
170  " skips '123-456' because it's older
171  call BackOne('-456')
172  call BackOne('3-456')
173  call BackOne('23-456')
174  call BackOne('123-456')
175  call assert_fails("BackOne('123-456')")
176  normal 10g+
177  call assert_equal('123-', getline(1))
178
179  :" Jump two seconds and go some seconds forward and backward
180  call test_settime(103)
181  call feedkeys("Aa\<Esc>", 'xt')
182  call feedkeys("Ab\<Esc>", 'xt')
183  call feedkeys("Ac\<Esc>", 'xt')
184  call assert_equal('123-abc', getline(1))
185  earlier 1s
186  call assert_equal('123-', getline(1))
187  earlier 3s
188  call assert_equal('123-456', getline(1))
189  later 1s
190  call assert_equal('123-', getline(1))
191  later 1h
192  call assert_equal('123-abc', getline(1))
193
194  close!
195endfunc
196
197func Test_undolist()
198  new
199  set ul=100
200
201  let a = execute('undolist')
202  call assert_equal("\nNothing to undo", a)
203
204  " 1 leaf (2 changes).
205  call feedkeys('achange1', 'xt')
206  call feedkeys('achange2', 'xt')
207  let a = execute('undolist')
208  call assert_match("^\nnumber changes  when  *saved\n *2  *2 .*$", a)
209
210  " 2 leaves.
211  call feedkeys('u', 'xt')
212  call feedkeys('achange3\<Esc>', 'xt')
213  let a = execute('undolist')
214  call assert_match("^\nnumber changes  when  *saved\n *2  *2  *.*\n *3  *2 .*$", a)
215  close!
216endfunc
217
218func Test_U_command()
219  new
220  set ul=100
221  call feedkeys("achange1\<Esc>", 'xt')
222  call feedkeys("achange2\<Esc>", 'xt')
223  norm! U
224  call assert_equal('', getline(1))
225  norm! U
226  call assert_equal('change1change2', getline(1))
227  close!
228endfunc
229
230func Test_undojoin()
231  new
232  call feedkeys("Goaaaa\<Esc>", 'xt')
233  call feedkeys("obbbb\<Esc>", 'xt')
234  call assert_equal(['aaaa', 'bbbb'], getline(2, '$'))
235  call feedkeys("u", 'xt')
236  call assert_equal(['aaaa'], getline(2, '$'))
237  call feedkeys("obbbb\<Esc>", 'xt')
238  undojoin
239  " Note: next change must not be as if typed
240  call feedkeys("occcc\<Esc>", 'x')
241  call assert_equal(['aaaa', 'bbbb', 'cccc'], getline(2, '$'))
242  call feedkeys("u", 'xt')
243  call assert_equal(['aaaa'], getline(2, '$'))
244  bwipe!
245endfunc
246
247func Test_undojoin_redo()
248  new
249  call setline(1, ['first line', 'second line'])
250  call feedkeys("ixx\<Esc>", 'xt')
251  call feedkeys(":undojoin | redo\<CR>", 'xt')
252  call assert_equal('xxfirst line', getline(1))
253  call assert_equal('second line', getline(2))
254  bwipe!
255endfunc
256
257" undojoin not allowed after undo
258func Test_undojoin_after_undo()
259  new
260  call feedkeys("ixx\<Esc>u", 'xt')
261  call assert_fails(':undojoin', 'E790:')
262  bwipe!
263endfunc
264
265" undojoin is a noop when no change yet, or when 'undolevels' is negative
266func Test_undojoin_noop()
267  new
268  call feedkeys(":undojoin\<CR>", 'xt')
269  call assert_equal([''], getline(1, '$'))
270  setlocal undolevels=-1
271  call feedkeys("ixx\<Esc>u", 'xt')
272  call feedkeys(":undojoin\<CR>", 'xt')
273  call assert_equal(['xx'], getline(1, '$'))
274  bwipe!
275endfunc
276
277func Test_undo_write()
278  call delete('Xtest')
279  split Xtest
280  call feedkeys("ione one one\<Esc>", 'xt')
281  w!
282  call feedkeys("otwo\<Esc>", 'xt')
283  call feedkeys("otwo\<Esc>", 'xt')
284  w
285  call feedkeys("othree\<Esc>", 'xt')
286  call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
287  earlier 1f
288  call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
289  earlier 1f
290  call assert_equal(['one one one'], getline(1, '$'))
291  earlier 1f
292  call assert_equal([''], getline(1, '$'))
293  later 1f
294  call assert_equal(['one one one'], getline(1, '$'))
295  later 1f
296  call assert_equal(['one one one', 'two', 'two'], getline(1, '$'))
297  later 1f
298  call assert_equal(['one one one', 'two', 'two', 'three'], getline(1, '$'))
299
300  close!
301  call delete('Xtest')
302  bwipe! Xtest
303
304  call assert_fails('earlier xyz', 'E475:')
305endfunc
306
307func Test_insert_expr()
308  new
309  " calling setline() triggers undo sync
310  call feedkeys("oa\<Esc>", 'xt')
311  call feedkeys("ob\<Esc>", 'xt')
312  set ul=100
313  call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
314  call assert_equal(['a', 'b', '120', '34'], getline(2, '$'))
315  call feedkeys("u", 'x')
316  call assert_equal(['a', 'b', '12'], getline(2, '$'))
317  call feedkeys("u", 'x')
318  call assert_equal(['a', 'b'], getline(2, '$'))
319
320  call feedkeys("oc\<Esc>", 'xt')
321  set ul=100
322  call feedkeys("o1\<Esc>a2\<C-R>=setline('.','1234')\<CR>\<CR>\<Esc>", 'x')
323  call assert_equal(['a', 'b', 'c', '120', '34'], getline(2, '$'))
324  call feedkeys("u", 'x')
325  call assert_equal(['a', 'b', 'c', '12'], getline(2, '$'))
326
327  call feedkeys("od\<Esc>", 'xt')
328  set ul=100
329  call feedkeys("o1\<Esc>a2\<C-R>=string(123)\<CR>\<Esc>", 'x')
330  call assert_equal(['a', 'b', 'c', '12', 'd', '12123'], getline(2, '$'))
331  call feedkeys("u", 'x')
332  call assert_equal(['a', 'b', 'c', '12', 'd'], getline(2, '$'))
333
334  close!
335endfunc
336
337func Test_undofile_earlier()
338  " Issue #1254
339  " create undofile with timestamps older than Vim startup time.
340  let t0 = localtime() - 43200
341  call test_settime(t0)
342  new Xfile
343  call feedkeys("ione\<Esc>", 'xt')
344  set ul=100
345  call test_settime(t0 + 1)
346  call feedkeys("otwo\<Esc>", 'xt')
347  set ul=100
348  call test_settime(t0 + 2)
349  call feedkeys("othree\<Esc>", 'xt')
350  set ul=100
351  w
352  wundo Xundofile
353  bwipe!
354  " restore normal timestamps.
355  call test_settime(0)
356  new Xfile
357  rundo Xundofile
358  earlier 1d
359  call assert_equal('', getline(1))
360  bwipe!
361  call delete('Xfile')
362  call delete('Xundofile')
363endfunc
364
365func Test_wundo_errors()
366  new
367  call setline(1, 'hello')
368  call assert_fails('wundo! Xdoesnotexist/Xundofile', 'E828:')
369  bwipe!
370endfunc
371
372" Check that reading a truncated undo file doesn't hang.
373func Test_undofile_truncated()
374  new
375  call setline(1, 'hello')
376  set ul=100
377  wundo Xundofile
378  let contents = readfile('Xundofile', 'B')
379
380  " try several sizes
381  for size in range(20, 500, 33)
382    call writefile(contents[0:size], 'Xundofile')
383    call assert_fails('rundo Xundofile', 'E825:')
384  endfor
385
386  bwipe!
387  call delete('Xundofile')
388endfunc
389
390func Test_rundo_errors()
391  call assert_fails('rundo XfileDoesNotExist', 'E822:')
392
393  call writefile(['abc'], 'Xundofile')
394  call assert_fails('rundo Xundofile', 'E823:')
395
396  call delete('Xundofile')
397endfunc
398
399func Test_undofile_next()
400  set undofile
401  new Xfoo.txt
402  execute "norm ix\<c-g>uy\<c-g>uz\<Esc>"
403  write
404  bwipe
405
406  next Xfoo.txt
407  call assert_equal('xyz', getline(1))
408  silent undo
409  call assert_equal('xy', getline(1))
410  silent undo
411  call assert_equal('x', getline(1))
412  bwipe!
413
414  call delete('Xfoo.txt')
415  call delete('.Xfoo.txt.un~')
416  set undofile&
417endfunc
418
419" Test for undo working properly when executing commands from a register.
420" Also test this in an empty buffer.
421func Test_cmd_in_reg_undo()
422  enew!
423  let @a = "Ox\<Esc>jAy\<Esc>kdd"
424  edit +/^$ test_undo.vim
425  normal @au
426  call assert_equal(0, &modified)
427  return
428  new
429  normal @au
430  call assert_equal(0, &modified)
431  only!
432  let @a = ''
433endfunc
434
435" This used to cause an illegal memory access
436func Test_undo_append()
437  new
438  call feedkeys("axx\<Esc>v", 'xt')
439  undo
440  norm o
441  quit
442endfunc
443
444func Test_undo_0()
445  new
446  set ul=100
447  normal i1
448  undo
449  normal i2
450  undo
451  normal i3
452
453  undo 0
454  let d = undotree()
455  call assert_equal('', getline(1))
456  call assert_equal(0, d.seq_cur)
457
458  redo
459  let d = undotree()
460  call assert_equal('3', getline(1))
461  call assert_equal(3, d.seq_cur)
462
463  undo 2
464  undo 0
465  let d = undotree()
466  call assert_equal('', getline(1))
467  call assert_equal(0, d.seq_cur)
468
469  redo
470  let d = undotree()
471  call assert_equal('2', getline(1))
472  call assert_equal(2, d.seq_cur)
473
474  undo 1
475  undo 0
476  let d = undotree()
477  call assert_equal('', getline(1))
478  call assert_equal(0, d.seq_cur)
479
480  redo
481  let d = undotree()
482  call assert_equal('1', getline(1))
483  call assert_equal(1, d.seq_cur)
484
485  bwipe!
486endfunc
487
488" undo or redo are noop if there is nothing to undo or redo
489func Test_undo_redo_noop()
490  new
491  call assert_fails('undo 2', 'E830:')
492
493  message clear
494  undo
495  let messages = split(execute('message'), "\n")
496  call assert_equal('Already at oldest change', messages[-1])
497
498  message clear
499  redo
500  let messages = split(execute('message'), "\n")
501  call assert_equal('Already at newest change', messages[-1])
502
503  bwipe!
504endfunc
505
506func Test_redo_empty_line()
507  new
508  exe "norm\x16r\x160"
509  exe "norm."
510  bwipe!
511endfunc
512
513funct Test_undofile()
514  " Test undofile() without setting 'undodir'.
515  if has('persistent_undo')
516    call assert_equal(fnamemodify('.Xundofoo.un~', ':p'), undofile('Xundofoo'))
517  else
518    call assert_equal('', undofile('Xundofoo'))
519  endif
520  call assert_equal('', undofile(''))
521
522  " Test undofile() with 'undodir' set to to an existing directory.
523  call mkdir('Xundodir')
524  set undodir=Xundodir
525  let cwd = getcwd()
526  if has('win32')
527    " Replace windows drive such as C:... into C%...
528    let cwd = substitute(cwd, '^\([a-zA-Z]\):', '\1%', 'g')
529  endif
530  let cwd = substitute(cwd . '/Xundofoo', '/', '%', 'g')
531  if has('persistent_undo')
532    call assert_equal('Xundodir/' . cwd, undofile('Xundofoo'))
533  else
534    call assert_equal('', undofile('Xundofoo'))
535  endif
536  call assert_equal('', undofile(''))
537  call delete('Xundodir', 'd')
538
539  " Test undofile() with 'undodir' set to a non-existing directory.
540  call assert_equal('', 'Xundofoo'->undofile())
541
542  if !has('win32') && isdirectory('/tmp')
543    set undodir=/tmp
544    if has('osx')
545      call assert_equal('/tmp/%private%tmp%file', undofile('///tmp/file'))
546    else
547      call assert_equal('/tmp/%tmp%file', undofile('///tmp/file'))
548    endif
549  endif
550
551  set undodir&
552endfunc
553
554" Tests for the undo file
555" Explicitly break changes up in undo-able pieces by setting 'undolevels'.
556func Test_undofile_2()
557  set undolevels=100 undofile
558  edit Xtestfile
559  call append(0, 'this is one line')
560  call cursor(1, 1)
561
562  " first a simple one-line change.
563  set undolevels=100
564  s/one/ONE/
565  set undolevels=100
566  write
567  bwipe!
568  edit Xtestfile
569  undo
570  call assert_equal('this is one line', getline(1))
571
572  " change in original file fails check
573  set noundofile
574  edit! Xtestfile
575  s/line/Line/
576  write
577  set undofile
578  bwipe!
579  edit Xtestfile
580  undo
581  call assert_equal('this is ONE Line', getline(1))
582
583  " add 10 lines, delete 6 lines, undo 3
584  set undofile
585  call setbufline(0, 1, ['one', 'two', 'three', 'four', 'five', 'six',
586	      \ 'seven', 'eight', 'nine', 'ten'])
587  set undolevels=100
588  normal 3Gdd
589  set undolevels=100
590  normal dd
591  set undolevels=100
592  normal dd
593  set undolevels=100
594  normal dd
595  set undolevels=100
596  normal dd
597  set undolevels=100
598  normal dd
599  set undolevels=100
600  write
601  bwipe!
602  edit Xtestfile
603  normal uuu
604  call assert_equal(['one', 'two', 'six', 'seven', 'eight', 'nine', 'ten'],
605	      \ getline(1, '$'))
606
607  " Test that reading the undofiles when setting undofile works
608  set noundofile undolevels=0
609  exe "normal i\n"
610  undo
611  edit! Xtestfile
612  set undofile undolevels=100
613  normal uuuuuu
614  call assert_equal(['one', 'two', 'three', 'four', 'five', 'six', 'seven',
615	      \ 'eight', 'nine', 'ten'], getline(1, '$'))
616
617  bwipe!
618  call delete('Xtestfile')
619  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
620  call delete(ufile)
621  set undofile& undolevels&
622endfunc
623
624" Test 'undofile' using a file encrypted with 'zip' crypt method
625func Test_undofile_cryptmethod_zip()
626  edit Xtestfile
627  set undofile cryptmethod=zip
628  call append(0, ['monday', 'tuesday', 'wednesday', 'thursday', 'friday'])
629  call cursor(5, 1)
630
631  set undolevels=100
632  normal kkkdd
633  set undolevels=100
634  normal dd
635  set undolevels=100
636  normal dd
637  set undolevels=100
638  " encrypt the file using key 'foobar'
639  call feedkeys("foobar\nfoobar\n")
640  X
641  write!
642  bwipe!
643
644  call feedkeys("foobar\n")
645  edit Xtestfile
646  set key=
647  normal uu
648  call assert_equal(['monday', 'wednesday', 'thursday', 'friday', ''],
649                    \ getline(1, '$'))
650
651  bwipe!
652  call delete('Xtestfile')
653  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
654  call delete(ufile)
655  set undofile& undolevels& cryptmethod&
656endfunc
657
658" Test 'undofile' using a file encrypted with 'blowfish' crypt method
659func Test_undofile_cryptmethod_blowfish()
660  edit Xtestfile
661  set undofile cryptmethod=blowfish
662  call append(0, ['jan', 'feb', 'mar', 'apr', 'jun'])
663  call cursor(5, 1)
664
665  set undolevels=100
666  exe 'normal kk0ifoo '
667  set undolevels=100
668  normal dd
669  set undolevels=100
670  exe 'normal ibar '
671  set undolevels=100
672  " encrypt the file using key 'foobar'
673  call feedkeys("foobar\nfoobar\n")
674  X
675  write!
676  bwipe!
677
678  call feedkeys("foobar\n")
679  edit Xtestfile
680  set key=
681  call search('bar')
682  call assert_equal('bar apr', getline('.'))
683  undo
684  call assert_equal('apr', getline('.'))
685  undo
686  call assert_equal('foo mar', getline('.'))
687  undo
688  call assert_equal('mar', getline('.'))
689
690  bwipe!
691  call delete('Xtestfile')
692  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
693  call delete(ufile)
694  set undofile& undolevels& cryptmethod&
695endfunc
696
697" Test 'undofile' using a file encrypted with 'blowfish2' crypt method
698func Test_undofile_cryptmethod_blowfish2()
699  edit Xtestfile
700  set undofile cryptmethod=blowfish2
701  call append(0, ['jan', 'feb', 'mar', 'apr', 'jun'])
702  call cursor(5, 1)
703
704  set undolevels=100
705  exe 'normal kk0ifoo '
706  set undolevels=100
707  normal dd
708  set undolevels=100
709  exe 'normal ibar '
710  set undolevels=100
711  " encrypt the file using key 'foo2bar'
712  call feedkeys("foo2bar\nfoo2bar\n")
713  X
714  write!
715  bwipe!
716
717  call feedkeys("foo2bar\n")
718  edit Xtestfile
719  set key=
720  call search('bar')
721  call assert_equal('bar apr', getline('.'))
722  normal u
723  call assert_equal('apr', getline('.'))
724  normal u
725  call assert_equal('foo mar', getline('.'))
726  normal u
727  call assert_equal('mar', getline('.'))
728
729  bwipe!
730  call delete('Xtestfile')
731  let ufile = has('vms') ? '_un_Xtestfile' : '.Xtestfile.un~'
732  call delete(ufile)
733  set undofile& undolevels& cryptmethod&
734endfunc
735
736" Test for redoing with incrementing numbered registers
737func Test_redo_repeat_numbered_register()
738  new
739  for [i, v] in [[1, 'one'], [2, 'two'], [3, 'three'],
740        \ [4, 'four'], [5, 'five'], [6, 'six'],
741        \ [7, 'seven'], [8, 'eight'], [9, 'nine']]
742    exe 'let @' .. i .. '="' .. v .. '\n"'
743  endfor
744  call feedkeys('"1p.........', 'xt')
745  call assert_equal(['', 'one', 'two', 'three', 'four', 'five', 'six',
746        \ 'seven', 'eight', 'nine', 'nine'], getline(1, '$'))
747  bwipe!
748endfunc
749
750" Test for redo in insert mode using CTRL-O with multibyte characters
751func Test_redo_multibyte_in_insert_mode()
752  new
753  call feedkeys("a\<C-K>ft", 'xt')
754  call feedkeys("uiHe\<C-O>.llo", 'xt')
755  call assert_equal("He\ufb05llo", getline(1))
756  bwipe!
757endfunc
758
759" vim: shiftwidth=2 sts=2 expandtab
760