xref: /vim-8.2.3635/src/testdir/test_autocmd.vim (revision e16b00a1)
1" Tests for autocommands
2
3set belloff=all
4
5func! s:cleanup_buffers() abort
6  for bnr in range(1, bufnr('$'))
7    if bufloaded(bnr) && bufnr('%') != bnr
8      execute 'bd! ' . bnr
9    endif
10  endfor
11endfunc
12
13func Test_vim_did_enter()
14  call assert_false(v:vim_did_enter)
15
16  " This script will never reach the main loop, can't check if v:vim_did_enter
17  " becomes one.
18endfunc
19
20if has('timers')
21  func ExitInsertMode(id)
22    call feedkeys("\<Esc>")
23  endfunc
24
25  func Test_cursorhold_insert()
26    " Need to move the cursor.
27    call feedkeys("ggG", "xt")
28
29    let g:triggered = 0
30    au CursorHoldI * let g:triggered += 1
31    set updatetime=20
32    call timer_start(100, 'ExitInsertMode')
33    call feedkeys('a', 'x!')
34    call assert_equal(1, g:triggered)
35    au! CursorHoldI
36    set updatetime&
37  endfunc
38
39  func Test_cursorhold_insert_ctrl_x()
40    let g:triggered = 0
41    au CursorHoldI * let g:triggered += 1
42    set updatetime=20
43    call timer_start(100, 'ExitInsertMode')
44    " CursorHoldI does not trigger after CTRL-X
45    call feedkeys("a\<C-X>", 'x!')
46    call assert_equal(0, g:triggered)
47    au! CursorHoldI
48    set updatetime&
49  endfunc
50endif
51
52func Test_bufunload()
53  augroup test_bufunload_group
54    autocmd!
55    autocmd BufUnload * call add(s:li, "bufunload")
56    autocmd BufDelete * call add(s:li, "bufdelete")
57    autocmd BufWipeout * call add(s:li, "bufwipeout")
58  augroup END
59
60  let s:li=[]
61  new
62  setlocal bufhidden=
63  bunload
64  call assert_equal(["bufunload", "bufdelete"], s:li)
65
66  let s:li=[]
67  new
68  setlocal bufhidden=delete
69  bunload
70  call assert_equal(["bufunload", "bufdelete"], s:li)
71
72  let s:li=[]
73  new
74  setlocal bufhidden=unload
75  bwipeout
76  call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li)
77
78  au! test_bufunload_group
79  augroup! test_bufunload_group
80endfunc
81
82" SEGV occurs in older versions.  (At least 7.4.2005 or older)
83func Test_autocmd_bufunload_with_tabnext()
84  tabedit
85  tabfirst
86
87  augroup test_autocmd_bufunload_with_tabnext_group
88    autocmd!
89    autocmd BufUnload <buffer> tabnext
90  augroup END
91
92  quit
93  call assert_equal(2, tabpagenr('$'))
94
95  autocmd! test_autocmd_bufunload_with_tabnext_group
96  augroup! test_autocmd_bufunload_with_tabnext_group
97  tablast
98  quit
99endfunc
100
101func Test_autocmd_bufwinleave_with_tabfirst()
102  tabedit
103  augroup sample
104    autocmd!
105    autocmd BufWinLeave <buffer> tabfirst
106  augroup END
107  call setline(1, ['a', 'b', 'c'])
108  edit! a.txt
109  tabclose
110endfunc
111
112" SEGV occurs in older versions.  (At least 7.4.2321 or older)
113func Test_autocmd_bufunload_avoiding_SEGV_01()
114  split aa.txt
115  let lastbuf = bufnr('$')
116
117  augroup test_autocmd_bufunload
118    autocmd!
119    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
120  augroup END
121
122  call assert_fails('edit bb.txt', 'E937:')
123
124  autocmd! test_autocmd_bufunload
125  augroup! test_autocmd_bufunload
126  bwipe! aa.txt
127  bwipe! bb.txt
128endfunc
129
130" SEGV occurs in older versions.  (At least 7.4.2321 or older)
131func Test_autocmd_bufunload_avoiding_SEGV_02()
132  setlocal buftype=nowrite
133  let lastbuf = bufnr('$')
134
135  augroup test_autocmd_bufunload
136    autocmd!
137    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
138  augroup END
139
140  normal! i1
141  call assert_fails('edit a.txt', 'E517:')
142  call feedkeys("\<CR>")
143
144  autocmd! test_autocmd_bufunload
145  augroup! test_autocmd_bufunload
146  bwipe! a.txt
147endfunc
148
149func Test_win_tab_autocmd()
150  let g:record = []
151
152  augroup testing
153    au WinNew * call add(g:record, 'WinNew')
154    au WinEnter * call add(g:record, 'WinEnter')
155    au WinLeave * call add(g:record, 'WinLeave')
156    au TabNew * call add(g:record, 'TabNew')
157    au TabClosed * call add(g:record, 'TabClosed')
158    au TabEnter * call add(g:record, 'TabEnter')
159    au TabLeave * call add(g:record, 'TabLeave')
160  augroup END
161
162  split
163  tabnew
164  close
165  close
166
167  call assert_equal([
168	\ 'WinLeave', 'WinNew', 'WinEnter',
169	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
170	\ 'WinLeave', 'TabLeave', 'TabClosed', 'WinEnter', 'TabEnter',
171	\ 'WinLeave', 'WinEnter'
172	\ ], g:record)
173
174  let g:record = []
175  tabnew somefile
176  tabnext
177  bwipe somefile
178
179  call assert_equal([
180	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
181	\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
182	\ 'TabClosed'
183	\ ], g:record)
184
185  augroup testing
186    au!
187  augroup END
188  unlet g:record
189endfunc
190
191func s:AddAnAutocmd()
192  augroup vimBarTest
193    au BufReadCmd * echo 'hello'
194  augroup END
195  call assert_equal(3, len(split(execute('au vimBarTest'), "\n")))
196endfunc
197
198func Test_early_bar()
199  " test that a bar is recognized before the {event}
200  call s:AddAnAutocmd()
201  augroup vimBarTest | au! | augroup END
202  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
203
204  call s:AddAnAutocmd()
205  augroup vimBarTest| au!| augroup END
206  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
207
208  " test that a bar is recognized after the {event}
209  call s:AddAnAutocmd()
210  augroup vimBarTest| au!BufReadCmd| augroup END
211  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
212
213  " test that a bar is recognized after the {group}
214  call s:AddAnAutocmd()
215  au! vimBarTest|echo 'hello'
216  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
217endfunc
218
219func RemoveGroup()
220  autocmd! StartOK
221  augroup! StartOK
222endfunc
223
224func Test_augroup_warning()
225  augroup TheWarning
226    au VimEnter * echo 'entering'
227  augroup END
228  call assert_true(match(execute('au VimEnter'), "TheWarning.*VimEnter") >= 0)
229  redir => res
230  augroup! TheWarning
231  redir END
232  call assert_true(match(res, "W19:") >= 0)
233  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
234
235  " check "Another" does not take the pace of the deleted entry
236  augroup Another
237  augroup END
238  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
239  augroup! Another
240
241  " no warning for postpone aucmd delete
242  augroup StartOK
243    au VimEnter * call RemoveGroup()
244  augroup END
245  call assert_true(match(execute('au VimEnter'), "StartOK.*VimEnter") >= 0)
246  redir => res
247  doautocmd VimEnter
248  redir END
249  call assert_true(match(res, "W19:") < 0)
250  au! VimEnter
251endfunc
252
253func Test_augroup_deleted()
254  " This caused a crash before E936 was introduced
255  augroup x
256    call assert_fails('augroup! x', 'E936:')
257    au VimEnter * echo
258  augroup end
259  augroup! x
260  call assert_true(match(execute('au VimEnter'), "-Deleted-.*VimEnter") >= 0)
261  au! VimEnter
262endfunc
263
264" Tests for autocommands on :close command.
265" This used to be in test13.
266func Test_three_windows()
267  " Clean up buffers, because in some cases this function fails.
268  call s:cleanup_buffers()
269
270  " Write three files and open them, each in a window.
271  " Then go to next window, with autocommand that deletes the previous one.
272  " Do this twice, writing the file.
273  e! Xtestje1
274  call setline(1, 'testje1')
275  w
276  sp Xtestje2
277  call setline(1, 'testje2')
278  w
279  sp Xtestje3
280  call setline(1, 'testje3')
281  w
282  wincmd w
283  au WinLeave Xtestje2 bwipe
284  wincmd w
285  call assert_equal('Xtestje1', expand('%'))
286
287  au WinLeave Xtestje1 bwipe Xtestje3
288  close
289  call assert_equal('Xtestje1', expand('%'))
290
291  " Test deleting the buffer on a Unload event.  If this goes wrong there
292  " will be the ATTENTION prompt.
293  e Xtestje1
294  au!
295  au! BufUnload Xtestje1 bwipe
296  call assert_fails('e Xtestje3', 'E937:')
297  call assert_equal('Xtestje3', expand('%'))
298
299  e Xtestje2
300  sp Xtestje1
301  call assert_fails('e', 'E937:')
302  call assert_equal('Xtestje2', expand('%'))
303
304  " Test changing buffers in a BufWipeout autocommand.  If this goes wrong
305  " there are ml_line errors and/or a Crash.
306  au!
307  only
308  e Xanother
309  e Xtestje1
310  bwipe Xtestje2
311  bwipe Xtestje3
312  au BufWipeout Xtestje1 buf Xtestje1
313  bwipe
314  call assert_equal('Xanother', expand('%'))
315
316  only
317  help
318  wincmd w
319  1quit
320  call assert_equal('Xanother', expand('%'))
321
322  au!
323  enew
324  bwipe! Xtestje1
325  call delete('Xtestje1')
326  call delete('Xtestje2')
327  call delete('Xtestje3')
328endfunc
329
330func Test_BufEnter()
331  au! BufEnter
332  au Bufenter * let val = val . '+'
333  let g:val = ''
334  split NewFile
335  call assert_equal('+', g:val)
336  bwipe!
337  call assert_equal('++', g:val)
338
339  " Also get BufEnter when editing a directory
340  call mkdir('Xdir')
341  split Xdir
342  call assert_equal('+++', g:val)
343
344  " On MS-Windows we can't edit the directory, make sure we wipe the right
345  " buffer.
346  bwipe! Xdir
347
348  call delete('Xdir', 'd')
349  au! BufEnter
350endfunc
351
352" Closing a window might cause an endless loop
353" E814 for older Vims
354func Test_autocmd_bufwipe_in_SessLoadPost()
355  tabnew
356  set noswapfile
357  mksession!
358
359  let content = ['set nocp noswapfile',
360        \ 'let v:swapchoice="e"',
361        \ 'augroup test_autocmd_sessionload',
362        \ 'autocmd!',
363        \ 'autocmd SessionLoadPost * 4bw!',
364        \ 'augroup END',
365	\ '',
366	\ 'func WriteErrors()',
367	\ '  call writefile([execute("messages")], "Xerrors")',
368	\ 'endfunc',
369	\ 'au VimLeave * call WriteErrors()',
370        \ ]
371  call writefile(content, 'Xvimrc')
372  call system(v:progpath. ' -u Xvimrc --not-a-term --noplugins -S Session.vim -c cq')
373  let errors = join(readfile('Xerrors'))
374  call assert_match('E814', errors)
375
376  set swapfile
377  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
378    call delete(file)
379  endfor
380endfunc
381
382" SEGV occurs in older versions.
383func Test_autocmd_bufwipe_in_SessLoadPost2()
384  tabnew
385  set noswapfile
386  mksession!
387
388  let content = ['set nocp noswapfile',
389      \ 'function! DeleteInactiveBufs()',
390      \ '  tabfirst',
391      \ '  let tabblist = []',
392      \ '  for i in range(1, tabpagenr(''$''))',
393      \ '    call extend(tabblist, tabpagebuflist(i))',
394      \ '  endfor',
395      \ '  for b in range(1, bufnr(''$''))',
396      \ '    if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')',
397      \ '      exec ''bwipeout '' . b',
398      \ '    endif',
399      \ '  endfor',
400      \ '  echomsg "SessionLoadPost DONE"',
401      \ 'endfunction',
402      \ 'au SessionLoadPost * call DeleteInactiveBufs()',
403      \ '',
404      \ 'func WriteErrors()',
405      \ '  call writefile([execute("messages")], "Xerrors")',
406      \ 'endfunc',
407      \ 'au VimLeave * call WriteErrors()',
408      \ ]
409  call writefile(content, 'Xvimrc')
410  call system(v:progpath. ' -u Xvimrc --not-a-term --noplugins -S Session.vim -c cq')
411  let errors = join(readfile('Xerrors'))
412  " This probably only ever matches on unix.
413  call assert_notmatch('Caught deadly signal SEGV', errors)
414  call assert_match('SessionLoadPost DONE', errors)
415
416  set swapfile
417  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
418    call delete(file)
419  endfor
420endfunc
421
422func Test_empty_doau()
423  doau \|
424endfunc
425
426func s:AutoCommandOptionSet(match)
427  let item     = remove(g:options, 0)
428  let expected = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", item[0], item[1], item[2], item[3])
429  let actual   = printf("Option: <%s>, Oldval: <%s>, NewVal: <%s>, Scope: <%s>\n", a:match, v:option_old, v:option_new, v:option_type)
430  let g:opt    = [expected, actual]
431  "call assert_equal(expected, actual)
432endfunc
433
434func Test_OptionSet()
435  if !has("eval") || !has("autocmd") || !exists("+autochdir")
436    return
437  endif
438
439  call test_override('starting', 1)
440  set nocp
441  au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
442
443  " 1: Setting number option"
444  let g:options=[['number', 0, 1, 'global']]
445  set nu
446  call assert_equal([], g:options)
447  call assert_equal(g:opt[0], g:opt[1])
448
449  " 2: Setting local number option"
450  let g:options=[['number', 1, 0, 'local']]
451  setlocal nonu
452  call assert_equal([], g:options)
453  call assert_equal(g:opt[0], g:opt[1])
454
455  " 3: Setting global number option"
456  let g:options=[['number', 1, 0, 'global']]
457  setglobal nonu
458  call assert_equal([], g:options)
459  call assert_equal(g:opt[0], g:opt[1])
460
461  " 4: Setting local autoindent option"
462  let g:options=[['autoindent', 0, 1, 'local']]
463  setlocal ai
464  call assert_equal([], g:options)
465  call assert_equal(g:opt[0], g:opt[1])
466
467  " 5: Setting global autoindent option"
468  let g:options=[['autoindent', 0, 1, 'global']]
469  setglobal ai
470  call assert_equal([], g:options)
471  call assert_equal(g:opt[0], g:opt[1])
472
473  " 6: Setting global autoindent option"
474  let g:options=[['autoindent', 1, 0, 'global']]
475  set ai!
476  call assert_equal([], g:options)
477  call assert_equal(g:opt[0], g:opt[1])
478
479  " Should not print anything, use :noa
480  " 7: don't trigger OptionSet"
481  let g:options=[['invalid', 1, 1, 'invalid']]
482  noa set nonu
483  call assert_equal([['invalid', 1, 1, 'invalid']], g:options)
484  call assert_equal(g:opt[0], g:opt[1])
485
486  " 8: Setting several global list and number option"
487  let g:options=[['list', 0, 1, 'global'], ['number', 0, 1, 'global']]
488  set list nu
489  call assert_equal([], g:options)
490  call assert_equal(g:opt[0], g:opt[1])
491
492  " 9: don't trigger OptionSet"
493  let g:options=[['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']]
494  noa set nolist nonu
495  call assert_equal([['invalid', 1, 1, 'invalid'], ['invalid', 1, 1, 'invalid']], g:options)
496  call assert_equal(g:opt[0], g:opt[1])
497
498  " 10: Setting global acd"
499  let g:options=[['autochdir', 0, 1, 'local']]
500  setlocal acd
501  call assert_equal([], g:options)
502  call assert_equal(g:opt[0], g:opt[1])
503
504  " 11: Setting global autoread (also sets local value)"
505  let g:options=[['autoread', 0, 1, 'global']]
506  set ar
507  call assert_equal([], g:options)
508  call assert_equal(g:opt[0], g:opt[1])
509
510  " 12: Setting local autoread"
511  let g:options=[['autoread', 1, 1, 'local']]
512  setlocal ar
513  call assert_equal([], g:options)
514  call assert_equal(g:opt[0], g:opt[1])
515
516  " 13: Setting global autoread"
517  let g:options=[['autoread', 1, 0, 'global']]
518  setglobal invar
519  call assert_equal([], g:options)
520  call assert_equal(g:opt[0], g:opt[1])
521
522  " 14: Setting option backspace through :let"
523  let g:options=[['backspace', '', 'eol,indent,start', 'global']]
524  let &bs="eol,indent,start"
525  call assert_equal([], g:options)
526  call assert_equal(g:opt[0], g:opt[1])
527
528  " 15: Setting option backspace through setbufvar()"
529  let g:options=[['backup', 0, 1, 'local']]
530  " try twice, first time, shouldn't trigger because option name is invalid,
531  " second time, it should trigger
532  call assert_fails("call setbufvar(1, '&l:bk', 1)", "E355")
533  " should trigger, use correct option name
534  call setbufvar(1, '&backup', 1)
535  call assert_equal([], g:options)
536  call assert_equal(g:opt[0], g:opt[1])
537
538  " 16: Setting number option using setwinvar"
539  let g:options=[['number', 0, 1, 'local']]
540  call setwinvar(0, '&number', 1)
541  call assert_equal([], g:options)
542  call assert_equal(g:opt[0], g:opt[1])
543
544  " 17: Setting key option, shouldn't trigger"
545  let g:options=[['key', 'invalid', 'invalid1', 'invalid']]
546  setlocal key=blah
547  setlocal key=
548  call assert_equal([['key', 'invalid', 'invalid1', 'invalid']], g:options)
549  call assert_equal(g:opt[0], g:opt[1])
550
551  " Cleanup
552  au! OptionSet
553  for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp']
554    exe printf(":set %s&vi", opt)
555  endfor
556  call test_override('starting', 0)
557  delfunc! AutoCommandOptionSet
558endfunc
559
560func Test_OptionSet_diffmode()
561  call test_override('starting', 1)
562  " 18: Changing an option when enetering diff mode
563  new
564  au OptionSet diff :let &l:cul=v:option_new
565
566  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
567  call assert_equal(0, &l:cul)
568  diffthis
569  call assert_equal(1, &l:cul)
570
571  vnew
572  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
573  call assert_equal(0, &l:cul)
574  diffthis
575  call assert_equal(1, &l:cul)
576
577  diffoff
578  call assert_equal(0, &l:cul)
579  call assert_equal(1, getwinvar(2, '&l:cul'))
580  bw!
581
582  call assert_equal(1, &l:cul)
583  diffoff!
584  call assert_equal(0, &l:cul)
585  call assert_equal(0, getwinvar(1, '&l:cul'))
586  bw!
587
588  " Cleanup
589  au! OptionSet
590  call test_override('starting', 0)
591endfunc
592
593func Test_OptionSet_diffmode_close()
594  call test_override('starting', 1)
595  " 19: Try to close the current window when entering diff mode
596  " should not segfault
597  new
598  au OptionSet diff close
599
600  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
601  call assert_fails(':diffthis', 'E788')
602  call assert_equal(1, &diff)
603  vnew
604  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
605  call assert_fails(':diffthis', 'E788')
606  call assert_equal(1, &diff)
607  bw!
608  call assert_fails(':diffoff!', 'E788')
609  bw!
610
611  " Cleanup
612  au! OptionSet
613  call test_override('starting', 0)
614  "delfunc! AutoCommandOptionSet
615endfunc
616
617" Test for Bufleave autocommand that deletes the buffer we are about to edit.
618func Test_BufleaveWithDelete()
619  new | edit Xfile1
620
621  augroup test_bufleavewithdelete
622      autocmd!
623      autocmd BufLeave Xfile1 bwipe Xfile2
624  augroup END
625
626  call assert_fails('edit Xfile2', 'E143:')
627  call assert_equal('Xfile1', bufname('%'))
628
629  autocmd! test_bufleavewithdelete BufLeave Xfile1
630  augroup! test_bufleavewithdelete
631
632  new
633  bwipe! Xfile1
634endfunc
635