xref: /vim-8.2.3635/src/testdir/test_autocmd.vim (revision b8e642f7)
1" Tests for autocommands
2
3source shared.vim
4source check.vim
5source term_util.vim
6
7func s:cleanup_buffers() abort
8  for bnr in range(1, bufnr('$'))
9    if bufloaded(bnr) && bufnr('%') != bnr
10      execute 'bd! ' . bnr
11    endif
12  endfor
13endfunc
14
15func Test_vim_did_enter()
16  call assert_false(v:vim_did_enter)
17
18  " This script will never reach the main loop, can't check if v:vim_did_enter
19  " becomes one.
20endfunc
21
22" Test for the CursorHold autocmd
23func Test_CursorHold_autocmd()
24  CheckRunVimInTerminal
25  call writefile(['one', 'two', 'three'], 'Xfile')
26  let before =<< trim END
27    set updatetime=10
28    au CursorHold * call writefile([line('.')], 'Xoutput', 'a')
29  END
30  call writefile(before, 'Xinit')
31  let buf = RunVimInTerminal('-S Xinit Xfile', {})
32  call term_sendkeys(buf, "G")
33  call term_wait(buf, 50)
34  call term_sendkeys(buf, "gg")
35  call term_wait(buf)
36  call WaitForAssert({-> assert_equal(['1'], readfile('Xoutput')[-1:-1])})
37  call term_sendkeys(buf, "j")
38  call term_wait(buf)
39  call WaitForAssert({-> assert_equal(['1', '2'], readfile('Xoutput')[-2:-1])})
40  call term_sendkeys(buf, "j")
41  call term_wait(buf)
42  call WaitForAssert({-> assert_equal(['1', '2', '3'], readfile('Xoutput')[-3:-1])})
43  call StopVimInTerminal(buf)
44
45  call delete('Xinit')
46  call delete('Xoutput')
47  call delete('Xfile')
48endfunc
49
50if has('timers')
51
52  func ExitInsertMode(id)
53    call feedkeys("\<Esc>")
54  endfunc
55
56  func Test_cursorhold_insert()
57    " Need to move the cursor.
58    call feedkeys("ggG", "xt")
59
60    let g:triggered = 0
61    au CursorHoldI * let g:triggered += 1
62    set updatetime=20
63    call timer_start(200, 'ExitInsertMode')
64    call feedkeys('a', 'x!')
65    call assert_equal(1, g:triggered)
66    unlet g:triggered
67    au! CursorHoldI
68    set updatetime&
69  endfunc
70
71  func Test_cursorhold_insert_with_timer_interrupt()
72    CheckFeature job
73    " Need to move the cursor.
74    call feedkeys("ggG", "xt")
75
76    " Confirm the timer invoked in exit_cb of the job doesn't disturb
77    " CursorHoldI event.
78    let g:triggered = 0
79    au CursorHoldI * let g:triggered += 1
80    set updatetime=100
81    call job_start(has('win32') ? 'cmd /c echo:' : 'echo',
82          \ {'exit_cb': {-> timer_start(200, 'ExitInsertMode')}})
83    call feedkeys('a', 'x!')
84    call assert_equal(1, g:triggered)
85    unlet g:triggered
86    au! CursorHoldI
87    set updatetime&
88  endfunc
89
90  func Test_cursorhold_insert_ctrl_x()
91    let g:triggered = 0
92    au CursorHoldI * let g:triggered += 1
93    set updatetime=20
94    call timer_start(100, 'ExitInsertMode')
95    " CursorHoldI does not trigger after CTRL-X
96    call feedkeys("a\<C-X>", 'x!')
97    call assert_equal(0, g:triggered)
98    unlet g:triggered
99    au! CursorHoldI
100    set updatetime&
101  endfunc
102
103  func Test_cursorhold_insert_ctrl_g_U()
104    au CursorHoldI * :
105    set updatetime=20
106    new
107    call timer_start(100, { -> feedkeys("\<Left>foo\<Esc>", 't') })
108    call feedkeys("i()\<C-g>U", 'tx!')
109    sleep 200m
110    call assert_equal('(foo)', getline(1))
111    undo
112    call assert_equal('', getline(1))
113
114    bwipe!
115    au! CursorHoldI
116    set updatetime&
117  endfunc
118
119  func Test_OptionSet_modeline()
120    call test_override('starting', 1)
121    au! OptionSet
122    augroup set_tabstop
123      au OptionSet tabstop call timer_start(1, {-> execute("echo 'Handler called'", "")})
124    augroup END
125    call writefile(['vim: set ts=7 sw=5 :', 'something'], 'XoptionsetModeline')
126    set modeline
127    let v:errmsg = ''
128    call assert_fails('split XoptionsetModeline', 'E12:')
129    call assert_equal(7, &ts)
130    call assert_equal('', v:errmsg)
131
132    augroup set_tabstop
133      au!
134    augroup END
135    bwipe!
136    set ts&
137    call delete('XoptionsetModeline')
138    call test_override('starting', 0)
139  endfunc
140
141endif "has('timers')
142
143func Test_bufunload()
144  augroup test_bufunload_group
145    autocmd!
146    autocmd BufUnload * call add(s:li, "bufunload")
147    autocmd BufDelete * call add(s:li, "bufdelete")
148    autocmd BufWipeout * call add(s:li, "bufwipeout")
149  augroup END
150
151  let s:li = []
152  new
153  setlocal bufhidden=
154  bunload
155  call assert_equal(["bufunload", "bufdelete"], s:li)
156
157  let s:li = []
158  new
159  setlocal bufhidden=delete
160  bunload
161  call assert_equal(["bufunload", "bufdelete"], s:li)
162
163  let s:li = []
164  new
165  setlocal bufhidden=unload
166  bwipeout
167  call assert_equal(["bufunload", "bufdelete", "bufwipeout"], s:li)
168
169  au! test_bufunload_group
170  augroup! test_bufunload_group
171endfunc
172
173" SEGV occurs in older versions.  (At least 7.4.2005 or older)
174func Test_autocmd_bufunload_with_tabnext()
175  tabedit
176  tabfirst
177
178  augroup test_autocmd_bufunload_with_tabnext_group
179    autocmd!
180    autocmd BufUnload <buffer> tabnext
181  augroup END
182
183  quit
184  call assert_equal(2, tabpagenr('$'))
185
186  autocmd! test_autocmd_bufunload_with_tabnext_group
187  augroup! test_autocmd_bufunload_with_tabnext_group
188  tablast
189  quit
190endfunc
191
192func Test_argdelete_in_next()
193  au BufNew,BufEnter,BufLeave,BufWinEnter * argdel
194  call assert_fails('next a b', 'E1156:')
195  au! BufNew,BufEnter,BufLeave,BufWinEnter *
196endfunc
197
198func Test_autocmd_bufwinleave_with_tabfirst()
199  tabedit
200  augroup sample
201    autocmd!
202    autocmd BufWinLeave <buffer> tabfirst
203  augroup END
204  call setline(1, ['a', 'b', 'c'])
205  edit! a.txt
206  tabclose
207endfunc
208
209" SEGV occurs in older versions.  (At least 7.4.2321 or older)
210func Test_autocmd_bufunload_avoiding_SEGV_01()
211  split aa.txt
212  let lastbuf = bufnr('$')
213
214  augroup test_autocmd_bufunload
215    autocmd!
216    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
217  augroup END
218
219  call assert_fails('edit bb.txt', 'E937:')
220
221  autocmd! test_autocmd_bufunload
222  augroup! test_autocmd_bufunload
223  bwipe! aa.txt
224  bwipe! bb.txt
225endfunc
226
227" SEGV occurs in older versions.  (At least 7.4.2321 or older)
228func Test_autocmd_bufunload_avoiding_SEGV_02()
229  setlocal buftype=nowrite
230  let lastbuf = bufnr('$')
231
232  augroup test_autocmd_bufunload
233    autocmd!
234    exe 'autocmd BufUnload <buffer> ' . (lastbuf + 1) . 'bwipeout!'
235  augroup END
236
237  normal! i1
238  call assert_fails('edit a.txt', 'E517:')
239
240  autocmd! test_autocmd_bufunload
241  augroup! test_autocmd_bufunload
242  bwipe! a.txt
243endfunc
244
245func Test_autocmd_dummy_wipeout()
246  " prepare files
247  call writefile([''], 'Xdummywipetest1.txt')
248  call writefile([''], 'Xdummywipetest2.txt')
249  augroup test_bufunload_group
250    autocmd!
251    autocmd BufUnload * call add(s:li, "bufunload")
252    autocmd BufDelete * call add(s:li, "bufdelete")
253    autocmd BufWipeout * call add(s:li, "bufwipeout")
254  augroup END
255
256  let s:li = []
257  split Xdummywipetest1.txt
258  silent! vimgrep /notmatched/ Xdummywipetest*
259  call assert_equal(["bufunload", "bufwipeout"], s:li)
260
261  bwipeout
262  call delete('Xdummywipetest1.txt')
263  call delete('Xdummywipetest2.txt')
264  au! test_bufunload_group
265  augroup! test_bufunload_group
266endfunc
267
268func Test_win_tab_autocmd()
269  let g:record = []
270
271  augroup testing
272    au WinNew * call add(g:record, 'WinNew')
273    au WinClosed * call add(g:record, 'WinClosed')
274    au WinEnter * call add(g:record, 'WinEnter')
275    au WinLeave * call add(g:record, 'WinLeave')
276    au TabNew * call add(g:record, 'TabNew')
277    au TabClosed * call add(g:record, 'TabClosed')
278    au TabEnter * call add(g:record, 'TabEnter')
279    au TabLeave * call add(g:record, 'TabLeave')
280  augroup END
281
282  split
283  tabnew
284  close
285  close
286
287  call assert_equal([
288	\ 'WinLeave', 'WinNew', 'WinEnter',
289	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
290	\ 'WinLeave', 'TabLeave', 'WinClosed', 'TabClosed', 'WinEnter', 'TabEnter',
291	\ 'WinLeave', 'WinClosed', 'WinEnter'
292	\ ], g:record)
293
294  let g:record = []
295  tabnew somefile
296  tabnext
297  bwipe somefile
298
299  call assert_equal([
300	\ 'WinLeave', 'TabLeave', 'WinNew', 'WinEnter', 'TabNew', 'TabEnter',
301	\ 'WinLeave', 'TabLeave', 'WinEnter', 'TabEnter',
302	\ 'WinClosed', 'TabClosed'
303	\ ], g:record)
304
305  augroup testing
306    au!
307  augroup END
308  unlet g:record
309endfunc
310
311func Test_WinClosed()
312  " Test that the pattern is matched against the closed window's ID, and both
313  " <amatch> and <afile> are set to it.
314  new
315  let winid = win_getid()
316  let g:matched = v:false
317  augroup test-WinClosed
318    autocmd!
319    execute 'autocmd WinClosed' winid 'let g:matched = v:true'
320    autocmd WinClosed * let g:amatch = str2nr(expand('<amatch>'))
321    autocmd WinClosed * let g:afile = str2nr(expand('<afile>'))
322  augroup END
323  close
324  call assert_true(g:matched)
325  call assert_equal(winid, g:amatch)
326  call assert_equal(winid, g:afile)
327
328  " Test that WinClosed is non-recursive.
329  new
330  new
331  call assert_equal(3, winnr('$'))
332  let g:triggered = 0
333  augroup test-WinClosed
334    autocmd!
335    autocmd WinClosed * let g:triggered += 1
336    autocmd WinClosed * 2 wincmd c
337  augroup END
338  close
339  call assert_equal(1, winnr('$'))
340  call assert_equal(1, g:triggered)
341
342  autocmd! test-WinClosed
343  augroup! test-WinClosed
344  unlet g:matched
345  unlet g:amatch
346  unlet g:afile
347  unlet g:triggered
348endfunc
349
350func s:AddAnAutocmd()
351  augroup vimBarTest
352    au BufReadCmd * echo 'hello'
353  augroup END
354  call assert_equal(3, len(split(execute('au vimBarTest'), "\n")))
355endfunc
356
357func Test_early_bar()
358  " test that a bar is recognized before the {event}
359  call s:AddAnAutocmd()
360  augroup vimBarTest | au! | let done = 77 | augroup END
361  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
362  call assert_equal(77, done)
363
364  call s:AddAnAutocmd()
365  augroup vimBarTest| au!| let done = 88 | augroup END
366  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
367  call assert_equal(88, done)
368
369  " test that a bar is recognized after the {event}
370  call s:AddAnAutocmd()
371  augroup vimBarTest| au!BufReadCmd| let done = 99 | augroup END
372  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
373  call assert_equal(99, done)
374
375  " test that a bar is recognized after the {group}
376  call s:AddAnAutocmd()
377  au! vimBarTest|echo 'hello'
378  call assert_equal(1, len(split(execute('au vimBarTest'), "\n")))
379endfunc
380
381func RemoveGroup()
382  autocmd! StartOK
383  augroup! StartOK
384endfunc
385
386func Test_augroup_warning()
387  augroup TheWarning
388    au VimEnter * echo 'entering'
389  augroup END
390  call assert_match("TheWarning.*VimEnter", execute('au VimEnter'))
391  redir => res
392  augroup! TheWarning
393  redir END
394  call assert_match("W19:", res)
395  call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
396
397  " check "Another" does not take the pace of the deleted entry
398  augroup Another
399  augroup END
400  call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
401  augroup! Another
402
403  " no warning for postpone aucmd delete
404  augroup StartOK
405    au VimEnter * call RemoveGroup()
406  augroup END
407  call assert_match("StartOK.*VimEnter", execute('au VimEnter'))
408  redir => res
409  doautocmd VimEnter
410  redir END
411  call assert_notmatch("W19:", res)
412  au! VimEnter
413
414  call assert_fails('augroup!', 'E471:')
415endfunc
416
417func Test_BufReadCmdHelp()
418  " This used to cause access to free memory
419  au BufReadCmd * e +h
420  help
421
422  au! BufReadCmd
423endfunc
424
425func Test_BufReadCmdHelpJump()
426  " This used to cause access to free memory
427  au BufReadCmd * e +h{
428  " } to fix highlighting
429  call assert_fails('help', 'E434:')
430
431  au! BufReadCmd
432endfunc
433
434func Test_augroup_deleted()
435  " This caused a crash before E936 was introduced
436  augroup x
437    call assert_fails('augroup! x', 'E936:')
438    au VimEnter * echo
439  augroup end
440  augroup! x
441  call assert_match("-Deleted-.*VimEnter", execute('au VimEnter'))
442  au! VimEnter
443endfunc
444
445" Tests for autocommands on :close command.
446" This used to be in test13.
447func Test_three_windows()
448  " Clean up buffers, because in some cases this function fails.
449  call s:cleanup_buffers()
450
451  " Write three files and open them, each in a window.
452  " Then go to next window, with autocommand that deletes the previous one.
453  " Do this twice, writing the file.
454  e! Xtestje1
455  call setline(1, 'testje1')
456  w
457  sp Xtestje2
458  call setline(1, 'testje2')
459  w
460  sp Xtestje3
461  call setline(1, 'testje3')
462  w
463  wincmd w
464  au WinLeave Xtestje2 bwipe
465  wincmd w
466  call assert_equal('Xtestje1', expand('%'))
467
468  au WinLeave Xtestje1 bwipe Xtestje3
469  close
470  call assert_equal('Xtestje1', expand('%'))
471
472  " Test deleting the buffer on a Unload event.  If this goes wrong there
473  " will be the ATTENTION prompt.
474  e Xtestje1
475  au!
476  au! BufUnload Xtestje1 bwipe
477  call assert_fails('e Xtestje3', 'E937:')
478  call assert_equal('Xtestje3', expand('%'))
479
480  e Xtestje2
481  sp Xtestje1
482  call assert_fails('e', 'E937:')
483  call assert_equal('Xtestje1', expand('%'))
484
485  " Test changing buffers in a BufWipeout autocommand.  If this goes wrong
486  " there are ml_line errors and/or a Crash.
487  au!
488  only
489  e Xanother
490  e Xtestje1
491  bwipe Xtestje2
492  bwipe Xtestje3
493  au BufWipeout Xtestje1 buf Xtestje1
494  bwipe
495  call assert_equal('Xanother', expand('%'))
496
497  only
498  help
499  wincmd w
500  1quit
501  call assert_equal('Xanother', expand('%'))
502
503  au!
504  enew
505  call delete('Xtestje1')
506  call delete('Xtestje2')
507  call delete('Xtestje3')
508endfunc
509
510func Test_BufEnter()
511  au! BufEnter
512  au Bufenter * let val = val . '+'
513  let g:val = ''
514  split NewFile
515  call assert_equal('+', g:val)
516  bwipe!
517  call assert_equal('++', g:val)
518
519  " Also get BufEnter when editing a directory
520  call mkdir('Xdir')
521  split Xdir
522  call assert_equal('+++', g:val)
523
524  " On MS-Windows we can't edit the directory, make sure we wipe the right
525  " buffer.
526  bwipe! Xdir
527
528  call delete('Xdir', 'd')
529  au! BufEnter
530endfunc
531
532" Closing a window might cause an endless loop
533" E814 for older Vims
534func Test_autocmd_bufwipe_in_SessLoadPost()
535  edit Xtest
536  tabnew
537  file Xsomething
538  set noswapfile
539  mksession!
540
541  let content =<< trim [CODE]
542    call test_override('ui_delay', 10)
543    set nocp noswapfile
544    let v:swapchoice = "e"
545    augroup test_autocmd_sessionload
546    autocmd!
547    autocmd SessionLoadPost * exe bufnr("Xsomething") . "bw!"
548    augroup END
549
550    func WriteErrors()
551      call writefile([execute("messages")], "Xerrors")
552    endfunc
553    au VimLeave * call WriteErrors()
554  [CODE]
555
556  call writefile(content, 'Xvimrc')
557  call system(GetVimCommand('Xvimrc') .. ' --not-a-term --noplugins -S Session.vim -c cq')
558  let errors = join(readfile('Xerrors'))
559  call assert_match('E814:', errors)
560
561  set swapfile
562  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
563    call delete(file)
564  endfor
565endfunc
566
567" Using :blast and :ball for many events caused a crash, because b_nwindows was
568" not incremented correctly.
569func Test_autocmd_blast_badd()
570  let content =<< trim [CODE]
571      au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* blast
572      edit foo1
573      au BufNew,BufAdd,BufWinEnter,BufEnter,BufLeave,BufWinLeave,BufUnload,VimEnter foo* ball
574      edit foo2
575      call writefile(['OK'], 'Xerrors')
576      qall
577  [CODE]
578
579  call writefile(content, 'XblastBall')
580  call system(GetVimCommand() .. ' --clean -S XblastBall')
581  call assert_match('OK', readfile('Xerrors')->join())
582
583  call delete('XblastBall')
584  call delete('Xerrors')
585endfunc
586
587" SEGV occurs in older versions.
588func Test_autocmd_bufwipe_in_SessLoadPost2()
589  tabnew
590  set noswapfile
591  mksession!
592
593  let content =<< trim [CODE]
594    set nocp noswapfile
595    function! DeleteInactiveBufs()
596      tabfirst
597      let tabblist = []
598      for i in range(1, tabpagenr(''$''))
599        call extend(tabblist, tabpagebuflist(i))
600      endfor
601      for b in range(1, bufnr(''$''))
602        if bufexists(b) && buflisted(b) && (index(tabblist, b) == -1 || bufname(b) =~# ''^$'')
603          exec ''bwipeout '' . b
604        endif
605      endfor
606      echomsg "SessionLoadPost DONE"
607    endfunction
608    au SessionLoadPost * call DeleteInactiveBufs()
609
610    func WriteErrors()
611      call writefile([execute("messages")], "Xerrors")
612    endfunc
613    au VimLeave * call WriteErrors()
614  [CODE]
615
616  call writefile(content, 'Xvimrc')
617  call system(GetVimCommand('Xvimrc') .. ' --not-a-term --noplugins -S Session.vim -c cq')
618  let errors = join(readfile('Xerrors'))
619  " This probably only ever matches on unix.
620  call assert_notmatch('Caught deadly signal SEGV', errors)
621  call assert_match('SessionLoadPost DONE', errors)
622
623  set swapfile
624  for file in ['Session.vim', 'Xvimrc', 'Xerrors']
625    call delete(file)
626  endfor
627endfunc
628
629func Test_empty_doau()
630  doau \|
631endfunc
632
633func s:AutoCommandOptionSet(match)
634  let template = "Option: <%s>, OldVal: <%s>, OldValLocal: <%s>, OldValGlobal: <%s>, NewVal: <%s>, Scope: <%s>, Command: <%s>\n"
635  let item     = remove(g:options, 0)
636  let expected = printf(template, item[0], item[1], item[2], item[3], item[4], item[5], item[6])
637  let actual   = printf(template, a:match, v:option_old, v:option_oldlocal, v:option_oldglobal, v:option_new, v:option_type, v:option_command)
638  let g:opt    = [expected, actual]
639  "call assert_equal(expected, actual)
640endfunc
641
642func Test_OptionSet()
643  CheckOption autochdir
644
645  badd test_autocmd.vim
646
647  call test_override('starting', 1)
648  set nocp
649  au OptionSet * :call s:AutoCommandOptionSet(expand("<amatch>"))
650
651  " 1: Setting number option"
652  let g:options = [['number', 0, 0, 0, 1, 'global', 'set']]
653  set nu
654  call assert_equal([], g:options)
655  call assert_equal(g:opt[0], g:opt[1])
656
657  " 2: Setting local number option"
658  let g:options = [['number', 1, 1, '', 0, 'local', 'setlocal']]
659  setlocal nonu
660  call assert_equal([], g:options)
661  call assert_equal(g:opt[0], g:opt[1])
662
663  " 3: Setting global number option"
664  let g:options = [['number', 1, '', 1, 0, 'global', 'setglobal']]
665  setglobal nonu
666  call assert_equal([], g:options)
667  call assert_equal(g:opt[0], g:opt[1])
668
669  " 4: Setting local autoindent option"
670  let g:options = [['autoindent', 0, 0, '', 1, 'local', 'setlocal']]
671  setlocal ai
672  call assert_equal([], g:options)
673  call assert_equal(g:opt[0], g:opt[1])
674
675  " 5: Setting global autoindent option"
676  let g:options = [['autoindent', 0, '', 0, 1, 'global', 'setglobal']]
677  setglobal ai
678  call assert_equal([], g:options)
679  call assert_equal(g:opt[0], g:opt[1])
680
681  " 6: Setting global autoindent option"
682  let g:options = [['autoindent', 1, 1, 1, 0, 'global', 'set']]
683  set ai!
684  call assert_equal([], g:options)
685  call assert_equal(g:opt[0], g:opt[1])
686
687  " 6a: Setting global autoindent option"
688  let g:options = [['autoindent', 1, 1, 0, 0, 'global', 'set']]
689  noa setlocal ai
690  noa setglobal noai
691  set ai!
692  call assert_equal([], g:options)
693  call assert_equal(g:opt[0], g:opt[1])
694
695  " Should not print anything, use :noa
696  " 7: don't trigger OptionSet"
697  let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
698  noa set nonu
699  call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
700  call assert_equal(g:opt[0], g:opt[1])
701
702  " 8: Setting several global list and number option"
703  let g:options = [['list', 0, 0, 0, 1, 'global', 'set'], ['number', 0, 0, 0, 1, 'global', 'set']]
704  set list nu
705  call assert_equal([], g:options)
706  call assert_equal(g:opt[0], g:opt[1])
707
708  " 9: don't trigger OptionSet"
709  let g:options = [['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']]
710  noa set nolist nonu
711  call assert_equal([['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid'], ['invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid', 'invalid']], g:options)
712  call assert_equal(g:opt[0], g:opt[1])
713
714  " 10: Setting global acd"
715  let g:options = [['autochdir', 0, 0, '', 1, 'local', 'setlocal']]
716  setlocal acd
717  call assert_equal([], g:options)
718  call assert_equal(g:opt[0], g:opt[1])
719
720  " 11: Setting global autoread (also sets local value)"
721  let g:options = [['autoread', 0, 0, 0, 1, 'global', 'set']]
722  set ar
723  call assert_equal([], g:options)
724  call assert_equal(g:opt[0], g:opt[1])
725
726  " 12: Setting local autoread"
727  let g:options = [['autoread', 1, 1, '', 1, 'local', 'setlocal']]
728  setlocal ar
729  call assert_equal([], g:options)
730  call assert_equal(g:opt[0], g:opt[1])
731
732  " 13: Setting global autoread"
733  let g:options = [['autoread', 1, '', 1, 0, 'global', 'setglobal']]
734  setglobal invar
735  call assert_equal([], g:options)
736  call assert_equal(g:opt[0], g:opt[1])
737
738  " 14: Setting option backspace through :let"
739  let g:options = [['backspace', '', '', '', 'eol,indent,start', 'global', 'set']]
740  let &bs = "eol,indent,start"
741  call assert_equal([], g:options)
742  call assert_equal(g:opt[0], g:opt[1])
743
744  " 15: Setting option backspace through setbufvar()"
745  let g:options = [['backup', 0, 0, '', 1, 'local', 'setlocal']]
746  " try twice, first time, shouldn't trigger because option name is invalid,
747  " second time, it should trigger
748  let bnum = bufnr('%')
749  call assert_fails("call setbufvar(bnum, '&l:bk', 1)", 'E355:')
750  " should trigger, use correct option name
751  call setbufvar(bnum, '&backup', 1)
752  call assert_equal([], g:options)
753  call assert_equal(g:opt[0], g:opt[1])
754
755  " 16: Setting number option using setwinvar"
756  let g:options = [['number', 0, 0, '', 1, 'local', 'setlocal']]
757  call setwinvar(0, '&number', 1)
758  call assert_equal([], g:options)
759  call assert_equal(g:opt[0], g:opt[1])
760
761  " 17: Setting key option, shouldn't trigger"
762  let g:options = [['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']]
763  setlocal key=blah
764  setlocal key=
765  call assert_equal([['key', 'invalid', 'invalid1', 'invalid2', 'invalid3', 'invalid4', 'invalid5']], g:options)
766  call assert_equal(g:opt[0], g:opt[1])
767
768
769  " 18a: Setting string global option"
770  let oldval = &backupext
771  let g:options = [['backupext', oldval, oldval, oldval, 'foo', 'global', 'set']]
772  set backupext=foo
773  call assert_equal([], g:options)
774  call assert_equal(g:opt[0], g:opt[1])
775
776  " 18b: Resetting string global option"
777  let g:options = [['backupext', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
778  set backupext&
779  call assert_equal([], g:options)
780  call assert_equal(g:opt[0], g:opt[1])
781
782  " 18c: Setting global string global option"
783  let g:options = [['backupext', oldval, '', oldval, 'bar', 'global', 'setglobal']]
784  setglobal backupext=bar
785  call assert_equal([], g:options)
786  call assert_equal(g:opt[0], g:opt[1])
787
788  " 18d: Setting local string global option"
789  " As this is a global option this sets the global value even though
790  " :setlocal is used!
791  noa set backupext& " Reset global and local value (without triggering autocmd)
792  let g:options = [['backupext', oldval, oldval, '', 'baz', 'local', 'setlocal']]
793  setlocal backupext=baz
794  call assert_equal([], g:options)
795  call assert_equal(g:opt[0], g:opt[1])
796
797  " 18e: Setting again string global option"
798  noa setglobal backupext=ext_global " Reset global and local value (without triggering autocmd)
799  noa setlocal backupext=ext_local " Sets the global(!) value!
800  let g:options = [['backupext', 'ext_local', 'ext_local', 'ext_local', 'fuu', 'global', 'set']]
801  set backupext=fuu
802  call assert_equal([], g:options)
803  call assert_equal(g:opt[0], g:opt[1])
804
805
806  " 19a: Setting string global-local (to buffer) option"
807  let oldval = &tags
808  let g:options = [['tags', oldval, oldval, oldval, 'tagpath', 'global', 'set']]
809  set tags=tagpath
810  call assert_equal([], g:options)
811  call assert_equal(g:opt[0], g:opt[1])
812
813  " 19b: Resetting string global-local (to buffer) option"
814  let g:options = [['tags', 'tagpath', 'tagpath', 'tagpath', oldval, 'global', 'set']]
815  set tags&
816  call assert_equal([], g:options)
817  call assert_equal(g:opt[0], g:opt[1])
818
819  " 19c: Setting global string global-local (to buffer) option "
820  let g:options = [['tags', oldval, '', oldval, 'tagpath1', 'global', 'setglobal']]
821  setglobal tags=tagpath1
822  call assert_equal([], g:options)
823  call assert_equal(g:opt[0], g:opt[1])
824
825  " 19d: Setting local string global-local (to buffer) option"
826  let g:options = [['tags', 'tagpath1', 'tagpath1', '', 'tagpath2', 'local', 'setlocal']]
827  setlocal tags=tagpath2
828  call assert_equal([], g:options)
829  call assert_equal(g:opt[0], g:opt[1])
830
831  " 19e: Setting again string global-local (to buffer) option"
832  " Note: v:option_old is the old global value for global-local string options
833  " but the old local value for all other kinds of options.
834  noa setglobal tags=tag_global " Reset global and local value (without triggering autocmd)
835  noa setlocal tags=tag_local
836  let g:options = [['tags', 'tag_global', 'tag_local', 'tag_global', 'tagpath', 'global', 'set']]
837  set tags=tagpath
838  call assert_equal([], g:options)
839  call assert_equal(g:opt[0], g:opt[1])
840
841  " 19f: Setting string global-local (to buffer) option to an empty string"
842  " Note: v:option_old is the old global value for global-local string options
843  " but the old local value for all other kinds of options.
844  noa set tags=tag_global " Reset global and local value (without triggering autocmd)
845  noa setlocal tags= " empty string
846  let g:options = [['tags', 'tag_global', '', 'tag_global', 'tagpath', 'global', 'set']]
847  set tags=tagpath
848  call assert_equal([], g:options)
849  call assert_equal(g:opt[0], g:opt[1])
850
851
852  " 20a: Setting string local (to buffer) option"
853  let oldval = &spelllang
854  let g:options = [['spelllang', oldval, oldval, oldval, 'elvish,klingon', 'global', 'set']]
855  set spelllang=elvish,klingon
856  call assert_equal([], g:options)
857  call assert_equal(g:opt[0], g:opt[1])
858
859  " 20b: Resetting string local (to buffer) option"
860  let g:options = [['spelllang', 'elvish,klingon', 'elvish,klingon', 'elvish,klingon', oldval, 'global', 'set']]
861  set spelllang&
862  call assert_equal([], g:options)
863  call assert_equal(g:opt[0], g:opt[1])
864
865  " 20c: Setting global string local (to buffer) option"
866  let g:options = [['spelllang', oldval, '', oldval, 'elvish', 'global', 'setglobal']]
867  setglobal spelllang=elvish
868  call assert_equal([], g:options)
869  call assert_equal(g:opt[0], g:opt[1])
870
871  " 20d: Setting local string local (to buffer) option"
872  noa set spelllang& " Reset global and local value (without triggering autocmd)
873  let g:options = [['spelllang', oldval, oldval, '', 'klingon', 'local', 'setlocal']]
874  setlocal spelllang=klingon
875  call assert_equal([], g:options)
876  call assert_equal(g:opt[0], g:opt[1])
877
878  " 20e: Setting again string local (to buffer) option"
879  " Note: v:option_old is the old global value for global-local string options
880  " but the old local value for all other kinds of options.
881  noa setglobal spelllang=spellglobal " Reset global and local value (without triggering autocmd)
882  noa setlocal spelllang=spelllocal
883  let g:options = [['spelllang', 'spelllocal', 'spelllocal', 'spellglobal', 'foo', 'global', 'set']]
884  set spelllang=foo
885  call assert_equal([], g:options)
886  call assert_equal(g:opt[0], g:opt[1])
887
888
889  " 21a: Setting string global-local (to window) option"
890  let oldval = &statusline
891  let g:options = [['statusline', oldval, oldval, oldval, 'foo', 'global', 'set']]
892  set statusline=foo
893  call assert_equal([], g:options)
894  call assert_equal(g:opt[0], g:opt[1])
895
896  " 21b: Resetting string global-local (to window) option"
897  " Note: v:option_old is the old global value for global-local string options
898  " but the old local value for all other kinds of options.
899  let g:options = [['statusline', 'foo', 'foo', 'foo', oldval, 'global', 'set']]
900  set statusline&
901  call assert_equal([], g:options)
902  call assert_equal(g:opt[0], g:opt[1])
903
904  " 21c: Setting global string global-local (to window) option"
905  let g:options = [['statusline', oldval, '', oldval, 'bar', 'global', 'setglobal']]
906  setglobal statusline=bar
907  call assert_equal([], g:options)
908  call assert_equal(g:opt[0], g:opt[1])
909
910  " 21d: Setting local string global-local (to window) option"
911  noa set statusline& " Reset global and local value (without triggering autocmd)
912  let g:options = [['statusline', oldval, oldval, '', 'baz', 'local', 'setlocal']]
913  setlocal statusline=baz
914  call assert_equal([], g:options)
915  call assert_equal(g:opt[0], g:opt[1])
916
917  " 21e: Setting again string global-local (to window) option"
918  " Note: v:option_old is the old global value for global-local string options
919  " but the old local value for all other kinds of options.
920  noa setglobal statusline=bar " Reset global and local value (without triggering autocmd)
921  noa setlocal statusline=baz
922  let g:options = [['statusline', 'bar', 'baz', 'bar', 'foo', 'global', 'set']]
923  set statusline=foo
924  call assert_equal([], g:options)
925  call assert_equal(g:opt[0], g:opt[1])
926
927
928  " 22a: Setting string local (to window) option"
929  let oldval = &foldignore
930  let g:options = [['foldignore', oldval, oldval, oldval, 'fo', 'global', 'set']]
931  set foldignore=fo
932  call assert_equal([], g:options)
933  call assert_equal(g:opt[0], g:opt[1])
934
935  " 22b: Resetting string local (to window) option"
936  let g:options = [['foldignore', 'fo', 'fo', 'fo', oldval, 'global', 'set']]
937  set foldignore&
938  call assert_equal([], g:options)
939  call assert_equal(g:opt[0], g:opt[1])
940
941  " 22c: Setting global string local (to window) option"
942  let g:options = [['foldignore', oldval, '', oldval, 'bar', 'global', 'setglobal']]
943  setglobal foldignore=bar
944  call assert_equal([], g:options)
945  call assert_equal(g:opt[0], g:opt[1])
946
947  " 22d: Setting local string local (to window) option"
948  noa set foldignore& " Reset global and local value (without triggering autocmd)
949  let g:options = [['foldignore', oldval, oldval, '', 'baz', 'local', 'setlocal']]
950  setlocal foldignore=baz
951  call assert_equal([], g:options)
952  call assert_equal(g:opt[0], g:opt[1])
953
954  " 22e: Setting again string local (to window) option"
955  noa setglobal foldignore=glob " Reset global and local value (without triggering autocmd)
956  noa setlocal foldignore=loc
957  let g:options = [['foldignore', 'loc', 'loc', 'glob', 'fo', 'global', 'set']]
958  set foldignore=fo
959  call assert_equal([], g:options)
960  call assert_equal(g:opt[0], g:opt[1])
961
962
963  " 23a: Setting global number global option"
964  noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
965  noa setlocal cmdheight=1 " Sets the global(!) value!
966  let g:options = [['cmdheight', '1', '', '1', '2', 'global', 'setglobal']]
967  setglobal cmdheight=2
968  call assert_equal([], g:options)
969  call assert_equal(g:opt[0], g:opt[1])
970
971  " 23b: Setting local number global option"
972  noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
973  noa setlocal cmdheight=1 " Sets the global(!) value!
974  let g:options = [['cmdheight', '1', '1', '', '2', 'local', 'setlocal']]
975  setlocal cmdheight=2
976  call assert_equal([], g:options)
977  call assert_equal(g:opt[0], g:opt[1])
978
979  " 23c: Setting again number global option"
980  noa setglobal cmdheight=8 " Reset global and local value (without triggering autocmd)
981  noa setlocal cmdheight=1 " Sets the global(!) value!
982  let g:options = [['cmdheight', '1', '1', '1', '2', 'global', 'set']]
983  set cmdheight=2
984  call assert_equal([], g:options)
985  call assert_equal(g:opt[0], g:opt[1])
986
987  " 23d: Setting again number global option"
988  noa set cmdheight=8 " Reset global and local value (without triggering autocmd)
989  let g:options = [['cmdheight', '8', '8', '8', '2', 'global', 'set']]
990  set cmdheight=2
991  call assert_equal([], g:options)
992  call assert_equal(g:opt[0], g:opt[1])
993
994
995  " 24a: Setting global number global-local (to buffer) option"
996  noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
997  noa setlocal undolevels=1
998  let g:options = [['undolevels', '8', '', '8', '2', 'global', 'setglobal']]
999  setglobal undolevels=2
1000  call assert_equal([], g:options)
1001  call assert_equal(g:opt[0], g:opt[1])
1002
1003  " 24b: Setting local number global-local (to buffer) option"
1004  noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
1005  noa setlocal undolevels=1
1006  let g:options = [['undolevels', '1', '1', '', '2', 'local', 'setlocal']]
1007  setlocal undolevels=2
1008  call assert_equal([], g:options)
1009  call assert_equal(g:opt[0], g:opt[1])
1010
1011  " 24c: Setting again number global-local (to buffer) option"
1012  noa setglobal undolevels=8 " Reset global and local value (without triggering autocmd)
1013  noa setlocal undolevels=1
1014  let g:options = [['undolevels', '1', '1', '8', '2', 'global', 'set']]
1015  set undolevels=2
1016  call assert_equal([], g:options)
1017  call assert_equal(g:opt[0], g:opt[1])
1018
1019  " 24d: Setting again global number global-local (to buffer) option"
1020  noa set undolevels=8 " Reset global and local value (without triggering autocmd)
1021  let g:options = [['undolevels', '8', '8', '8', '2', 'global', 'set']]
1022  set undolevels=2
1023  call assert_equal([], g:options)
1024  call assert_equal(g:opt[0], g:opt[1])
1025
1026
1027  " 25a: Setting global number local (to buffer) option"
1028  noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
1029  noa setlocal wrapmargin=1
1030  let g:options = [['wrapmargin', '8', '', '8', '2', 'global', 'setglobal']]
1031  setglobal wrapmargin=2
1032  call assert_equal([], g:options)
1033  call assert_equal(g:opt[0], g:opt[1])
1034
1035  " 25b: Setting local number local (to buffer) option"
1036  noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
1037  noa setlocal wrapmargin=1
1038  let g:options = [['wrapmargin', '1', '1', '', '2', 'local', 'setlocal']]
1039  setlocal wrapmargin=2
1040  call assert_equal([], g:options)
1041  call assert_equal(g:opt[0], g:opt[1])
1042
1043  " 25c: Setting again number local (to buffer) option"
1044  noa setglobal wrapmargin=8 " Reset global and local value (without triggering autocmd)
1045  noa setlocal wrapmargin=1
1046  let g:options = [['wrapmargin', '1', '1', '8', '2', 'global', 'set']]
1047  set wrapmargin=2
1048  call assert_equal([], g:options)
1049  call assert_equal(g:opt[0], g:opt[1])
1050
1051  " 25d: Setting again global number local (to buffer) option"
1052  noa set wrapmargin=8 " Reset global and local value (without triggering autocmd)
1053  let g:options = [['wrapmargin', '8', '8', '8', '2', 'global', 'set']]
1054  set wrapmargin=2
1055  call assert_equal([], g:options)
1056  call assert_equal(g:opt[0], g:opt[1])
1057
1058
1059  " 26: Setting number global-local (to window) option.
1060  " Such option does currently not exist.
1061
1062
1063  " 27a: Setting global number local (to window) option"
1064  noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
1065  noa setlocal foldcolumn=1
1066  let g:options = [['foldcolumn', '8', '', '8', '2', 'global', 'setglobal']]
1067  setglobal foldcolumn=2
1068  call assert_equal([], g:options)
1069  call assert_equal(g:opt[0], g:opt[1])
1070
1071  " 27b: Setting local number local (to window) option"
1072  noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
1073  noa setlocal foldcolumn=1
1074  let g:options = [['foldcolumn', '1', '1', '', '2', 'local', 'setlocal']]
1075  setlocal foldcolumn=2
1076  call assert_equal([], g:options)
1077  call assert_equal(g:opt[0], g:opt[1])
1078
1079  " 27c: Setting again number local (to window) option"
1080  noa setglobal foldcolumn=8 " Reset global and local value (without triggering autocmd)
1081  noa setlocal foldcolumn=1
1082  let g:options = [['foldcolumn', '1', '1', '8', '2', 'global', 'set']]
1083  set foldcolumn=2
1084  call assert_equal([], g:options)
1085  call assert_equal(g:opt[0], g:opt[1])
1086
1087  " 27d: Setting again global number local (to window) option"
1088  noa set foldcolumn=8 " Reset global and local value (without triggering autocmd)
1089  let g:options = [['foldcolumn', '8', '8', '8', '2', 'global', 'set']]
1090  set foldcolumn=2
1091  call assert_equal([], g:options)
1092  call assert_equal(g:opt[0], g:opt[1])
1093
1094
1095  " 28a: Setting global boolean global option"
1096  noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
1097  noa setlocal wrapscan " Sets the global(!) value!
1098  let g:options = [['wrapscan', '1', '', '1', '0', 'global', 'setglobal']]
1099  setglobal nowrapscan
1100  call assert_equal([], g:options)
1101  call assert_equal(g:opt[0], g:opt[1])
1102
1103  " 28b: Setting local boolean global option"
1104  noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
1105  noa setlocal wrapscan " Sets the global(!) value!
1106  let g:options = [['wrapscan', '1', '1', '', '0', 'local', 'setlocal']]
1107  setlocal nowrapscan
1108  call assert_equal([], g:options)
1109  call assert_equal(g:opt[0], g:opt[1])
1110
1111  " 28c: Setting again boolean global option"
1112  noa setglobal nowrapscan " Reset global and local value (without triggering autocmd)
1113  noa setlocal wrapscan " Sets the global(!) value!
1114  let g:options = [['wrapscan', '1', '1', '1', '0', 'global', 'set']]
1115  set nowrapscan
1116  call assert_equal([], g:options)
1117  call assert_equal(g:opt[0], g:opt[1])
1118
1119  " 28d: Setting again global boolean global option"
1120  noa set nowrapscan " Reset global and local value (without triggering autocmd)
1121  let g:options = [['wrapscan', '0', '0', '0', '1', 'global', 'set']]
1122  set wrapscan
1123  call assert_equal([], g:options)
1124  call assert_equal(g:opt[0], g:opt[1])
1125
1126
1127  " 29a: Setting global boolean global-local (to buffer) option"
1128  noa setglobal noautoread " Reset global and local value (without triggering autocmd)
1129  noa setlocal autoread
1130  let g:options = [['autoread', '0', '', '0', '1', 'global', 'setglobal']]
1131  setglobal autoread
1132  call assert_equal([], g:options)
1133  call assert_equal(g:opt[0], g:opt[1])
1134
1135  " 29b: Setting local boolean global-local (to buffer) option"
1136  noa setglobal noautoread " Reset global and local value (without triggering autocmd)
1137  noa setlocal autoread
1138  let g:options = [['autoread', '1', '1', '', '0', 'local', 'setlocal']]
1139  setlocal noautoread
1140  call assert_equal([], g:options)
1141  call assert_equal(g:opt[0], g:opt[1])
1142
1143  " 29c: Setting again boolean global-local (to buffer) option"
1144  noa setglobal noautoread " Reset global and local value (without triggering autocmd)
1145  noa setlocal autoread
1146  let g:options = [['autoread', '1', '1', '0', '1', 'global', 'set']]
1147  set autoread
1148  call assert_equal([], g:options)
1149  call assert_equal(g:opt[0], g:opt[1])
1150
1151  " 29d: Setting again global boolean global-local (to buffer) option"
1152  noa set noautoread " Reset global and local value (without triggering autocmd)
1153  let g:options = [['autoread', '0', '0', '0', '1', 'global', 'set']]
1154  set autoread
1155  call assert_equal([], g:options)
1156  call assert_equal(g:opt[0], g:opt[1])
1157
1158
1159  " 30a: Setting global boolean local (to buffer) option"
1160  noa setglobal nocindent " Reset global and local value (without triggering autocmd)
1161  noa setlocal cindent
1162  let g:options = [['cindent', '0', '', '0', '1', 'global', 'setglobal']]
1163  setglobal cindent
1164  call assert_equal([], g:options)
1165  call assert_equal(g:opt[0], g:opt[1])
1166
1167  " 30b: Setting local boolean local (to buffer) option"
1168  noa setglobal nocindent " Reset global and local value (without triggering autocmd)
1169  noa setlocal cindent
1170  let g:options = [['cindent', '1', '1', '', '0', 'local', 'setlocal']]
1171  setlocal nocindent
1172  call assert_equal([], g:options)
1173  call assert_equal(g:opt[0], g:opt[1])
1174
1175  " 30c: Setting again boolean local (to buffer) option"
1176  noa setglobal nocindent " Reset global and local value (without triggering autocmd)
1177  noa setlocal cindent
1178  let g:options = [['cindent', '1', '1', '0', '1', 'global', 'set']]
1179  set cindent
1180  call assert_equal([], g:options)
1181  call assert_equal(g:opt[0], g:opt[1])
1182
1183  " 30d: Setting again global boolean local (to buffer) option"
1184  noa set nocindent " Reset global and local value (without triggering autocmd)
1185  let g:options = [['cindent', '0', '0', '0', '1', 'global', 'set']]
1186  set cindent
1187  call assert_equal([], g:options)
1188  call assert_equal(g:opt[0], g:opt[1])
1189
1190
1191  " 31: Setting boolean global-local (to window) option
1192  " Currently no such option exists.
1193
1194
1195  " 32a: Setting global boolean local (to window) option"
1196  noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
1197  noa setlocal cursorcolumn
1198  let g:options = [['cursorcolumn', '0', '', '0', '1', 'global', 'setglobal']]
1199  setglobal cursorcolumn
1200  call assert_equal([], g:options)
1201  call assert_equal(g:opt[0], g:opt[1])
1202
1203  " 32b: Setting local boolean local (to window) option"
1204  noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
1205  noa setlocal cursorcolumn
1206  let g:options = [['cursorcolumn', '1', '1', '', '0', 'local', 'setlocal']]
1207  setlocal nocursorcolumn
1208  call assert_equal([], g:options)
1209  call assert_equal(g:opt[0], g:opt[1])
1210
1211  " 32c: Setting again boolean local (to window) option"
1212  noa setglobal nocursorcolumn " Reset global and local value (without triggering autocmd)
1213  noa setlocal cursorcolumn
1214  let g:options = [['cursorcolumn', '1', '1', '0', '1', 'global', 'set']]
1215  set cursorcolumn
1216  call assert_equal([], g:options)
1217  call assert_equal(g:opt[0], g:opt[1])
1218
1219  " 32d: Setting again global boolean local (to window) option"
1220  noa set nocursorcolumn " Reset global and local value (without triggering autocmd)
1221  let g:options = [['cursorcolumn', '0', '0', '0', '1', 'global', 'set']]
1222  set cursorcolumn
1223  call assert_equal([], g:options)
1224  call assert_equal(g:opt[0], g:opt[1])
1225
1226
1227  " 33: Test autocommands when an option value is converted internally.
1228  noa set backspace=1 " Reset global and local value (without triggering autocmd)
1229  let g:options = [['backspace', 'indent,eol', 'indent,eol', 'indent,eol', '2', 'global', 'set']]
1230  set backspace=2
1231  call assert_equal([], g:options)
1232  call assert_equal(g:opt[0], g:opt[1])
1233
1234
1235  " Cleanup
1236  au! OptionSet
1237  " set tags&
1238  for opt in ['nu', 'ai', 'acd', 'ar', 'bs', 'backup', 'cul', 'cp', 'backupext', 'tags', 'spelllang', 'statusline', 'foldignore', 'cmdheight', 'undolevels', 'wrapmargin', 'foldcolumn', 'wrapscan', 'autoread', 'cindent', 'cursorcolumn']
1239    exe printf(":set %s&vim", opt)
1240  endfor
1241  call test_override('starting', 0)
1242  delfunc! AutoCommandOptionSet
1243endfunc
1244
1245func Test_OptionSet_diffmode()
1246  call test_override('starting', 1)
1247  " 18: Changing an option when entering diff mode
1248  new
1249  au OptionSet diff :let &l:cul = v:option_new
1250
1251  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
1252  call assert_equal(0, &l:cul)
1253  diffthis
1254  call assert_equal(1, &l:cul)
1255
1256  vnew
1257  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
1258  call assert_equal(0, &l:cul)
1259  diffthis
1260  call assert_equal(1, &l:cul)
1261
1262  diffoff
1263  call assert_equal(0, &l:cul)
1264  call assert_equal(1, getwinvar(2, '&l:cul'))
1265  bw!
1266
1267  call assert_equal(1, &l:cul)
1268  diffoff!
1269  call assert_equal(0, &l:cul)
1270  call assert_equal(0, getwinvar(1, '&l:cul'))
1271  bw!
1272
1273  " Cleanup
1274  au! OptionSet
1275  call test_override('starting', 0)
1276endfunc
1277
1278func Test_OptionSet_diffmode_close()
1279  call test_override('starting', 1)
1280  " 19: Try to close the current window when entering diff mode
1281  " should not segfault
1282  new
1283  au OptionSet diff close
1284
1285  call setline(1, ['buffer 1', 'line2', 'line3', 'line4'])
1286  call assert_fails(':diffthis', 'E788:')
1287  call assert_equal(1, &diff)
1288  vnew
1289  call setline(1, ['buffer 2', 'line 2', 'line 3', 'line4'])
1290  call assert_fails(':diffthis', 'E788:')
1291  call assert_equal(1, &diff)
1292  set diffopt-=closeoff
1293  bw!
1294  call assert_fails(':diffoff!', 'E788:')
1295  bw!
1296
1297  " Cleanup
1298  au! OptionSet
1299  call test_override('starting', 0)
1300  "delfunc! AutoCommandOptionSet
1301endfunc
1302
1303" Test for Bufleave autocommand that deletes the buffer we are about to edit.
1304func Test_BufleaveWithDelete()
1305  new | edit Xfile1
1306
1307  augroup test_bufleavewithdelete
1308      autocmd!
1309      autocmd BufLeave Xfile1 bwipe Xfile2
1310  augroup END
1311
1312  call assert_fails('edit Xfile2', 'E143:')
1313  call assert_equal('Xfile1', bufname('%'))
1314
1315  autocmd! test_bufleavewithdelete BufLeave Xfile1
1316  augroup! test_bufleavewithdelete
1317
1318  new
1319  bwipe! Xfile1
1320endfunc
1321
1322" Test for autocommand that changes the buffer list, when doing ":ball".
1323func Test_Acmd_BufAll()
1324  enew!
1325  %bwipe!
1326  call writefile(['Test file Xxx1'], 'Xxx1')
1327  call writefile(['Test file Xxx2'], 'Xxx2')
1328  call writefile(['Test file Xxx3'], 'Xxx3')
1329
1330  " Add three files to the buffer list
1331  split Xxx1
1332  close
1333  split Xxx2
1334  close
1335  split Xxx3
1336  close
1337
1338  " Wipe the buffer when the buffer is opened
1339  au BufReadPost Xxx2 bwipe
1340
1341  call append(0, 'Test file Xxx4')
1342  ball
1343
1344  call assert_equal(2, winnr('$'))
1345  call assert_equal('Xxx1', bufname(winbufnr(winnr('$'))))
1346  wincmd t
1347
1348  au! BufReadPost
1349  %bwipe!
1350  call delete('Xxx1')
1351  call delete('Xxx2')
1352  call delete('Xxx3')
1353  enew! | only
1354endfunc
1355
1356" Test for autocommand that changes current buffer on BufEnter event.
1357" Check if modelines are interpreted for the correct buffer.
1358func Test_Acmd_BufEnter()
1359  %bwipe!
1360  call writefile(['start of test file Xxx1',
1361	      \ "\<Tab>this is a test",
1362	      \ 'end of test file Xxx1'], 'Xxx1')
1363  call writefile(['start of test file Xxx2',
1364	      \ 'vim: set noai :',
1365	      \ "\<Tab>this is a test",
1366	      \ 'end of test file Xxx2'], 'Xxx2')
1367
1368  au BufEnter Xxx2 brew
1369  set ai modeline modelines=3
1370  edit Xxx1
1371  " edit Xxx2, autocmd will do :brew
1372  edit Xxx2
1373  exe "normal G?this is a\<CR>"
1374  " Append text with autoindent to this file
1375  normal othis should be auto-indented
1376  call assert_equal("\<Tab>this should be auto-indented", getline('.'))
1377  call assert_equal(3, line('.'))
1378  " Remove autocmd and edit Xxx2 again
1379  au! BufEnter Xxx2
1380  buf! Xxx2
1381  exe "normal G?this is a\<CR>"
1382  " append text without autoindent to Xxx
1383  normal othis should be in column 1
1384  call assert_equal("this should be in column 1", getline('.'))
1385  call assert_equal(4, line('.'))
1386
1387  %bwipe!
1388  call delete('Xxx1')
1389  call delete('Xxx2')
1390  set ai&vim modeline&vim modelines&vim
1391endfunc
1392
1393" Test for issue #57
1394" do not move cursor on <c-o> when autoindent is set
1395func Test_ai_CTRL_O()
1396  enew!
1397  set ai
1398  let save_fo = &fo
1399  set fo+=r
1400  exe "normal o# abcdef\<Esc>2hi\<CR>\<C-O>d0\<Esc>"
1401  exe "normal o# abcdef\<Esc>2hi\<C-O>d0\<Esc>"
1402  call assert_equal(['# abc', 'def', 'def'], getline(2, 4))
1403
1404  set ai&vim
1405  let &fo = save_fo
1406  enew!
1407endfunc
1408
1409" Test for autocommand that deletes the current buffer on BufLeave event.
1410" Also test deleting the last buffer, should give a new, empty buffer.
1411func Test_BufLeave_Wipe()
1412  %bwipe!
1413  let content = ['start of test file Xxx',
1414	      \ 'this is a test',
1415	      \ 'end of test file Xxx']
1416  call writefile(content, 'Xxx1')
1417  call writefile(content, 'Xxx2')
1418
1419  au BufLeave Xxx2 bwipe
1420  edit Xxx1
1421  split Xxx2
1422  " delete buffer Xxx2, we should be back to Xxx1
1423  bwipe
1424  call assert_equal('Xxx1', bufname('%'))
1425  call assert_equal(1, winnr('$'))
1426
1427  " Create an alternate buffer
1428  %write! test.out
1429  call assert_equal('test.out', bufname('#'))
1430  " delete alternate buffer
1431  bwipe test.out
1432  call assert_equal('Xxx1', bufname('%'))
1433  call assert_equal('', bufname('#'))
1434
1435  au BufLeave Xxx1 bwipe
1436  " delete current buffer, get an empty one
1437  bwipe!
1438  call assert_equal(1, line('$'))
1439  call assert_equal('', bufname('%'))
1440  let g:bufinfo = getbufinfo()
1441  call assert_equal(1, len(g:bufinfo))
1442
1443  call delete('Xxx1')
1444  call delete('Xxx2')
1445  call delete('test.out')
1446  %bwipe
1447  au! BufLeave
1448
1449  " check that bufinfo doesn't contain a pointer to freed memory
1450  call test_garbagecollect_now()
1451endfunc
1452
1453func Test_QuitPre()
1454  edit Xfoo
1455  let winid = win_getid(winnr())
1456  split Xbar
1457  au! QuitPre * let g:afile = expand('<afile>')
1458  " Close the other window, <afile> should be correct.
1459  exe win_id2win(winid) . 'q'
1460  call assert_equal('Xfoo', g:afile)
1461
1462  unlet g:afile
1463  bwipe Xfoo
1464  bwipe Xbar
1465endfunc
1466
1467func Test_Cmdline()
1468  au! CmdlineChanged : let g:text = getcmdline()
1469  let g:text = 0
1470  call feedkeys(":echom 'hello'\<CR>", 'xt')
1471  call assert_equal("echom 'hello'", g:text)
1472  au! CmdlineChanged
1473
1474  au! CmdlineChanged : let g:entered = expand('<afile>')
1475  let g:entered = 0
1476  call feedkeys(":echom 'hello'\<CR>", 'xt')
1477  call assert_equal(':', g:entered)
1478  au! CmdlineChanged
1479
1480  au! CmdlineEnter : let g:entered = expand('<afile>')
1481  au! CmdlineLeave : let g:left = expand('<afile>')
1482  let g:entered = 0
1483  let g:left = 0
1484  call feedkeys(":echo 'hello'\<CR>", 'xt')
1485  call assert_equal(':', g:entered)
1486  call assert_equal(':', g:left)
1487  au! CmdlineEnter
1488  au! CmdlineLeave
1489
1490  let save_shellslash = &shellslash
1491  set noshellslash
1492  au! CmdlineEnter / let g:entered = expand('<afile>')
1493  au! CmdlineLeave / let g:left = expand('<afile>')
1494  let g:entered = 0
1495  let g:left = 0
1496  new
1497  call setline(1, 'hello')
1498  call feedkeys("/hello\<CR>", 'xt')
1499  call assert_equal('/', g:entered)
1500  call assert_equal('/', g:left)
1501  bwipe!
1502  au! CmdlineEnter
1503  au! CmdlineLeave
1504  let &shellslash = save_shellslash
1505endfunc
1506
1507" Test for BufWritePre autocommand that deletes or unloads the buffer.
1508func Test_BufWritePre()
1509  %bwipe
1510  au BufWritePre Xxx1 bunload
1511  au BufWritePre Xxx2 bwipe
1512
1513  call writefile(['start of Xxx1', 'test', 'end of Xxx1'], 'Xxx1')
1514  call writefile(['start of Xxx2', 'test', 'end of Xxx2'], 'Xxx2')
1515
1516  edit Xtest
1517  e! Xxx2
1518  bdel Xtest
1519  e Xxx1
1520  " write it, will unload it and give an error msg
1521  call assert_fails('w', 'E203:')
1522  call assert_equal('Xxx2', bufname('%'))
1523  edit Xtest
1524  e! Xxx2
1525  bwipe Xtest
1526  " write it, will delete the buffer and give an error msg
1527  call assert_fails('w', 'E203:')
1528  call assert_equal('Xxx1', bufname('%'))
1529  au! BufWritePre
1530  call delete('Xxx1')
1531  call delete('Xxx2')
1532endfunc
1533
1534" Test for BufUnload autocommand that unloads all the other buffers
1535func Test_bufunload_all()
1536  let g:test_is_flaky = 1
1537  call writefile(['Test file Xxx1'], 'Xxx1')"
1538  call writefile(['Test file Xxx2'], 'Xxx2')"
1539
1540  let content =<< trim [CODE]
1541    func UnloadAllBufs()
1542      let i = 1
1543      while i <= bufnr('$')
1544        if i != bufnr('%') && bufloaded(i)
1545          exe  i . 'bunload'
1546        endif
1547        let i += 1
1548      endwhile
1549    endfunc
1550    au BufUnload * call UnloadAllBufs()
1551    au VimLeave * call writefile(['Test Finished'], 'Xout')
1552    edit Xxx1
1553    split Xxx2
1554    q
1555  [CODE]
1556
1557  call writefile(content, 'Xtest')
1558
1559  call delete('Xout')
1560  call system(GetVimCommandClean() .. ' -N --not-a-term -S Xtest')
1561  call assert_true(filereadable('Xout'))
1562
1563  call delete('Xxx1')
1564  call delete('Xxx2')
1565  call delete('Xtest')
1566  call delete('Xout')
1567endfunc
1568
1569" Some tests for buffer-local autocommands
1570func Test_buflocal_autocmd()
1571  let g:bname = ''
1572  edit xx
1573  au BufLeave <buffer> let g:bname = expand("%")
1574  " here, autocommand for xx should trigger.
1575  " but autocommand shall not apply to buffer named <buffer>.
1576  edit somefile
1577  call assert_equal('xx', g:bname)
1578  let g:bname = ''
1579  " here, autocommand shall be auto-deleted
1580  bwipe xx
1581  " autocmd should not trigger
1582  edit xx
1583  call assert_equal('', g:bname)
1584  " autocmd should not trigger
1585  edit somefile
1586  call assert_equal('', g:bname)
1587  enew
1588  unlet g:bname
1589endfunc
1590
1591" Test for "*Cmd" autocommands
1592func Test_Cmd_Autocmds()
1593  call writefile(['start of Xxx', "\tabc2", 'end of Xxx'], 'Xxx')
1594
1595  enew!
1596  au BufReadCmd XtestA 0r Xxx|$del
1597  edit XtestA			" will read text of Xxd instead
1598  call assert_equal('start of Xxx', getline(1))
1599
1600  au BufWriteCmd XtestA call append(line("$"), "write")
1601  write				" will append a line to the file
1602  call assert_equal('write', getline('$'))
1603  call assert_fails('read XtestA', 'E484:')	" should not read anything
1604  call assert_equal('write', getline(4))
1605
1606  " now we have:
1607  " 1	start of Xxx
1608  " 2		abc2
1609  " 3	end of Xxx
1610  " 4	write
1611
1612  au FileReadCmd XtestB '[r Xxx
1613  2r XtestB			" will read Xxx below line 2 instead
1614  call assert_equal('start of Xxx', getline(3))
1615
1616  " now we have:
1617  " 1	start of Xxx
1618  " 2		abc2
1619  " 3	start of Xxx
1620  " 4		abc2
1621  " 5	end of Xxx
1622  " 6	end of Xxx
1623  " 7	write
1624
1625  au FileWriteCmd XtestC '[,']copy $
1626  normal 4GA1
1627  4,5w XtestC			" will copy lines 4 and 5 to the end
1628  call assert_equal("\tabc21", getline(8))
1629  call assert_fails('r XtestC', 'E484:')	" should not read anything
1630  call assert_equal("end of Xxx", getline(9))
1631
1632  " now we have:
1633  " 1	start of Xxx
1634  " 2		abc2
1635  " 3	start of Xxx
1636  " 4		abc21
1637  " 5	end of Xxx
1638  " 6	end of Xxx
1639  " 7	write
1640  " 8		abc21
1641  " 9	end of Xxx
1642
1643  let g:lines = []
1644  au FileAppendCmd XtestD call extend(g:lines, getline(line("'["), line("']")))
1645  w >>XtestD			" will add lines to 'lines'
1646  call assert_equal(9, len(g:lines))
1647  call assert_fails('$r XtestD', 'E484:')	" should not read anything
1648  call assert_equal(9, line('$'))
1649  call assert_equal('end of Xxx', getline('$'))
1650
1651  au BufReadCmd XtestE 0r Xxx|$del
1652  sp XtestE			" split window with test.out
1653  call assert_equal('end of Xxx', getline(3))
1654
1655  let g:lines = []
1656  exe "normal 2Goasdf\<Esc>\<C-W>\<C-W>"
1657  au BufWriteCmd XtestE call extend(g:lines, getline(0, '$'))
1658  wall				" will write other window to 'lines'
1659  call assert_equal(4, len(g:lines), g:lines)
1660  call assert_equal('asdf', g:lines[2])
1661
1662  au! BufReadCmd
1663  au! BufWriteCmd
1664  au! FileReadCmd
1665  au! FileWriteCmd
1666  au! FileAppendCmd
1667  %bwipe!
1668  call delete('Xxx')
1669  enew!
1670endfunc
1671
1672func s:ReadFile()
1673  setl noswapfile nomodified
1674  let filename = resolve(expand("<afile>:p"))
1675  execute 'read' fnameescape(filename)
1676  1d_
1677  exe 'file' fnameescape(filename)
1678  setl buftype=acwrite
1679endfunc
1680
1681func s:WriteFile()
1682  let filename = resolve(expand("<afile>:p"))
1683  setl buftype=
1684  noautocmd execute 'write' fnameescape(filename)
1685  setl buftype=acwrite
1686  setl nomodified
1687endfunc
1688
1689func Test_BufReadCmd()
1690  autocmd BufReadCmd *.test call s:ReadFile()
1691  autocmd BufWriteCmd *.test call s:WriteFile()
1692
1693  call writefile(['one', 'two', 'three'], 'Xcmd.test')
1694  edit Xcmd.test
1695  call assert_match('Xcmd.test" line 1 of 3', execute('file'))
1696  normal! Gofour
1697  write
1698  call assert_equal(['one', 'two', 'three', 'four'], readfile('Xcmd.test'))
1699
1700  bwipe!
1701  call delete('Xcmd.test')
1702  au! BufReadCmd
1703  au! BufWriteCmd
1704endfunc
1705
1706func SetChangeMarks(start, end)
1707  exe a:start .. 'mark ['
1708  exe a:end .. 'mark ]'
1709endfunc
1710
1711" Verify the effects of autocmds on '[ and ']
1712func Test_change_mark_in_autocmds()
1713  edit! Xtest
1714  call feedkeys("ia\<CR>b\<CR>c\<CR>d\<C-g>u\<Esc>", 'xtn')
1715
1716  call SetChangeMarks(2, 3)
1717  write
1718  call assert_equal([1, 4], [line("'["), line("']")])
1719
1720  call SetChangeMarks(2, 3)
1721  au BufWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1722  write
1723  au! BufWritePre
1724
1725  if has('unix')
1726    write XtestFilter
1727    write >> XtestFilter
1728
1729    call SetChangeMarks(2, 3)
1730    " Marks are set to the entire range of the write
1731    au FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
1732    " '[ is adjusted to just before the line that will receive the filtered
1733    " data
1734    au FilterReadPre * call assert_equal([4, 4], [line("'["), line("']")])
1735    " The filtered data is read into the buffer, and the source lines are
1736    " still present, so the range is after the source lines
1737    au FilterReadPost * call assert_equal([5, 12], [line("'["), line("']")])
1738    %!cat XtestFilter
1739    " After the filtered data is read, the original lines are deleted
1740    call assert_equal([1, 8], [line("'["), line("']")])
1741    au! FilterWritePre,FilterReadPre,FilterReadPost
1742    undo
1743
1744    call SetChangeMarks(1, 4)
1745    au FilterWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1746    au FilterReadPre * call assert_equal([3, 3], [line("'["), line("']")])
1747    au FilterReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1748    2,3!cat XtestFilter
1749    call assert_equal([2, 9], [line("'["), line("']")])
1750    au! FilterWritePre,FilterReadPre,FilterReadPost
1751    undo
1752
1753    call delete('XtestFilter')
1754  endif
1755
1756  call SetChangeMarks(1, 4)
1757  au FileWritePre * call assert_equal([2, 3], [line("'["), line("']")])
1758  2,3write Xtest2
1759  au! FileWritePre
1760
1761  call SetChangeMarks(2, 3)
1762  au FileAppendPre * call assert_equal([1, 4], [line("'["), line("']")])
1763  write >> Xtest2
1764  au! FileAppendPre
1765
1766  call SetChangeMarks(1, 4)
1767  au FileAppendPre * call assert_equal([2, 3], [line("'["), line("']")])
1768  2,3write >> Xtest2
1769  au! FileAppendPre
1770
1771  call SetChangeMarks(1, 1)
1772  au FileReadPre * call assert_equal([3, 1], [line("'["), line("']")])
1773  au FileReadPost * call assert_equal([4, 11], [line("'["), line("']")])
1774  3read Xtest2
1775  au! FileReadPre,FileReadPost
1776  undo
1777
1778  call SetChangeMarks(4, 4)
1779  " When the line is 0, it's adjusted to 1
1780  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1781  au FileReadPost * call assert_equal([1, 8], [line("'["), line("']")])
1782  0read Xtest2
1783  au! FileReadPre,FileReadPost
1784  undo
1785
1786  call SetChangeMarks(4, 4)
1787  " When the line is 0, it's adjusted to 1
1788  au FileReadPre * call assert_equal([1, 4], [line("'["), line("']")])
1789  au FileReadPost * call assert_equal([2, 9], [line("'["), line("']")])
1790  1read Xtest2
1791  au! FileReadPre,FileReadPost
1792  undo
1793
1794  bwipe!
1795  call delete('Xtest')
1796  call delete('Xtest2')
1797endfunc
1798
1799func Test_Filter_noshelltemp()
1800  CheckExecutable cat
1801
1802  enew!
1803  call setline(1, ['a', 'b', 'c', 'd'])
1804
1805  let shelltemp = &shelltemp
1806  set shelltemp
1807
1808  let g:filter_au = 0
1809  au FilterWritePre * let g:filter_au += 1
1810  au FilterReadPre * let g:filter_au += 1
1811  au FilterReadPost * let g:filter_au += 1
1812  %!cat
1813  call assert_equal(3, g:filter_au)
1814
1815  if has('filterpipe')
1816    set noshelltemp
1817
1818    let g:filter_au = 0
1819    au FilterWritePre * let g:filter_au += 1
1820    au FilterReadPre * let g:filter_au += 1
1821    au FilterReadPost * let g:filter_au += 1
1822    %!cat
1823    call assert_equal(0, g:filter_au)
1824  endif
1825
1826  au! FilterWritePre,FilterReadPre,FilterReadPost
1827  let &shelltemp = shelltemp
1828  bwipe!
1829endfunc
1830
1831func Test_TextYankPost()
1832  enew!
1833  call setline(1, ['foo'])
1834
1835  let g:event = []
1836  au TextYankPost * let g:event = copy(v:event)
1837
1838  call assert_equal({}, v:event)
1839  call assert_fails('let v:event = {}', 'E46:')
1840  call assert_fails('let v:event.mykey = 0', 'E742:')
1841
1842  norm "ayiw
1843  call assert_equal(
1844    \{'regcontents': ['foo'], 'regname': 'a', 'operator': 'y', 'regtype': 'v', 'visual': v:false},
1845    \g:event)
1846  norm y_
1847  call assert_equal(
1848    \{'regcontents': ['foo'], 'regname': '',  'operator': 'y', 'regtype': 'V', 'visual': v:false},
1849    \g:event)
1850  norm Vy
1851  call assert_equal(
1852    \{'regcontents': ['foo'], 'regname': '',  'operator': 'y', 'regtype': 'V', 'visual': v:true},
1853    \g:event)
1854  call feedkeys("\<C-V>y", 'x')
1855  call assert_equal(
1856    \{'regcontents': ['f'], 'regname': '',  'operator': 'y', 'regtype': "\x161", 'visual': v:true},
1857    \g:event)
1858  norm "xciwbar
1859  call assert_equal(
1860    \{'regcontents': ['foo'], 'regname': 'x', 'operator': 'c', 'regtype': 'v', 'visual': v:false},
1861    \g:event)
1862  norm "bdiw
1863  call assert_equal(
1864    \{'regcontents': ['bar'], 'regname': 'b', 'operator': 'd', 'regtype': 'v', 'visual': v:false},
1865    \g:event)
1866
1867  call assert_equal({}, v:event)
1868
1869  if has('clipboard_working') && !has('gui_running')
1870    " Test that when the visual selection is automatically copied to clipboard
1871    " register a TextYankPost is emitted
1872    call setline(1, ['foobar'])
1873
1874    let @* = ''
1875    set clipboard=autoselect
1876    exe "norm! ggviw\<Esc>"
1877    call assert_equal(
1878        \{'regcontents': ['foobar'], 'regname': '*', 'operator': 'y', 'regtype': 'v', 'visual': v:true},
1879        \g:event)
1880
1881    let @+ = ''
1882    set clipboard=autoselectplus
1883    exe "norm! ggviw\<Esc>"
1884    call assert_equal(
1885        \{'regcontents': ['foobar'], 'regname': '+', 'operator': 'y', 'regtype': 'v', 'visual': v:true},
1886        \g:event)
1887
1888    set clipboard&vim
1889  endif
1890
1891  au! TextYankPost
1892  unlet g:event
1893  bwipe!
1894endfunc
1895
1896func Test_autocommand_all_events()
1897  call assert_fails('au * * bwipe', 'E1155:')
1898  call assert_fails('au * x bwipe', 'E1155:')
1899endfunc
1900
1901function s:Before_test_dirchanged()
1902  augroup test_dirchanged
1903    autocmd!
1904  augroup END
1905  let s:li = []
1906  let s:dir_this = getcwd()
1907  let s:dir_foo = s:dir_this . '/Xfoo'
1908  call mkdir(s:dir_foo)
1909  let s:dir_bar = s:dir_this . '/Xbar'
1910  call mkdir(s:dir_bar)
1911endfunc
1912
1913function s:After_test_dirchanged()
1914  call chdir(s:dir_this)
1915  call delete(s:dir_foo, 'd')
1916  call delete(s:dir_bar, 'd')
1917  augroup test_dirchanged
1918    autocmd!
1919  augroup END
1920endfunc
1921
1922function Test_dirchanged_global()
1923  call s:Before_test_dirchanged()
1924  autocmd test_dirchanged DirChanged global call add(s:li, "cd:")
1925  autocmd test_dirchanged DirChanged global call add(s:li, expand("<afile>"))
1926  call chdir(s:dir_foo)
1927  call assert_equal(["cd:", s:dir_foo], s:li)
1928  call chdir(s:dir_foo)
1929  call assert_equal(["cd:", s:dir_foo], s:li)
1930  exe 'lcd ' .. fnameescape(s:dir_bar)
1931  call assert_equal(["cd:", s:dir_foo], s:li)
1932  call s:After_test_dirchanged()
1933endfunc
1934
1935function Test_dirchanged_local()
1936  call s:Before_test_dirchanged()
1937  autocmd test_dirchanged DirChanged window call add(s:li, "lcd:")
1938  autocmd test_dirchanged DirChanged window call add(s:li, expand("<afile>"))
1939  call chdir(s:dir_foo)
1940  call assert_equal([], s:li)
1941  exe 'lcd ' .. fnameescape(s:dir_bar)
1942  call assert_equal(["lcd:", s:dir_bar], s:li)
1943  exe 'lcd ' .. fnameescape(s:dir_bar)
1944  call assert_equal(["lcd:", s:dir_bar], s:li)
1945  call s:After_test_dirchanged()
1946endfunc
1947
1948function Test_dirchanged_auto()
1949  CheckOption autochdir
1950  call s:Before_test_dirchanged()
1951  call test_autochdir()
1952  autocmd test_dirchanged DirChanged auto call add(s:li, "auto:")
1953  autocmd test_dirchanged DirChanged auto call add(s:li, expand("<afile>"))
1954  set acd
1955  cd ..
1956  call assert_equal([], s:li)
1957  exe 'edit ' . s:dir_foo . '/Xfile'
1958  call assert_equal(s:dir_foo, getcwd())
1959  call assert_equal(["auto:", s:dir_foo], s:li)
1960  set noacd
1961  bwipe!
1962  call s:After_test_dirchanged()
1963endfunc
1964
1965" Test TextChangedI and TextChangedP
1966func Test_ChangedP()
1967  new
1968  call setline(1, ['foo', 'bar', 'foobar'])
1969  call test_override("char_avail", 1)
1970  set complete=. completeopt=menuone
1971
1972  func! TextChangedAutocmd(char)
1973    let g:autocmd .= a:char
1974  endfunc
1975
1976  " TextChanged will not be triggered, only check that it isn't.
1977  au! TextChanged <buffer> :call TextChangedAutocmd('N')
1978  au! TextChangedI <buffer> :call TextChangedAutocmd('I')
1979  au! TextChangedP <buffer> :call TextChangedAutocmd('P')
1980
1981  call cursor(3, 1)
1982  let g:autocmd = ''
1983  call feedkeys("o\<esc>", 'tnix')
1984  call assert_equal('I', g:autocmd)
1985
1986  let g:autocmd = ''
1987  call feedkeys("Sf", 'tnix')
1988  call assert_equal('II', g:autocmd)
1989
1990  let g:autocmd = ''
1991  call feedkeys("Sf\<C-N>", 'tnix')
1992  call assert_equal('IIP', g:autocmd)
1993
1994  let g:autocmd = ''
1995  call feedkeys("Sf\<C-N>\<C-N>", 'tnix')
1996  call assert_equal('IIPP', g:autocmd)
1997
1998  let g:autocmd = ''
1999  call feedkeys("Sf\<C-N>\<C-N>\<C-N>", 'tnix')
2000  call assert_equal('IIPPP', g:autocmd)
2001
2002  let g:autocmd = ''
2003  call feedkeys("Sf\<C-N>\<C-N>\<C-N>\<C-N>", 'tnix')
2004  call assert_equal('IIPPPP', g:autocmd)
2005
2006  call assert_equal(['foo', 'bar', 'foobar', 'foo'], getline(1, '$'))
2007  " TODO: how should it handle completeopt=noinsert,noselect?
2008
2009  " CleanUp
2010  call test_override("char_avail", 0)
2011  au! TextChanged
2012  au! TextChangedI
2013  au! TextChangedP
2014  delfu TextChangedAutocmd
2015  unlet! g:autocmd
2016  set complete&vim completeopt&vim
2017
2018  bw!
2019endfunc
2020
2021let g:setline_handled = v:false
2022func SetLineOne()
2023  if !g:setline_handled
2024    call setline(1, "(x)")
2025    let g:setline_handled = v:true
2026  endif
2027endfunc
2028
2029func Test_TextChangedI_with_setline()
2030  new
2031  call test_override('char_avail', 1)
2032  autocmd TextChangedI <buffer> call SetLineOne()
2033  call feedkeys("i(\<CR>\<Esc>", 'tx')
2034  call assert_equal('(', getline(1))
2035  call assert_equal('x)', getline(2))
2036  undo
2037  call assert_equal('', getline(1))
2038  call assert_equal('', getline(2))
2039
2040  call test_override('starting', 0)
2041  bwipe!
2042endfunc
2043
2044func Test_Changed_FirstTime()
2045  CheckFeature terminal
2046  CheckNotGui
2047  " Starting a terminal to run Vim is always considered flaky.
2048  let g:test_is_flaky = 1
2049
2050  " Prepare file for TextChanged event.
2051  call writefile([''], 'Xchanged.txt')
2052  let buf = term_start([GetVimProg(), '--clean', '-c', 'set noswapfile'], {'term_rows': 3})
2053  call assert_equal('running', term_getstatus(buf))
2054  " Wait for the ruler (in the status line) to be shown.
2055  " In ConPTY, there is additional character which is drawn up to the width of
2056  " the screen.
2057  if has('conpty')
2058    call WaitForAssert({-> assert_match('\<All.*$', term_getline(buf, 3))})
2059  else
2060    call WaitForAssert({-> assert_match('\<All$', term_getline(buf, 3))})
2061  endif
2062  " It's only adding autocmd, so that no event occurs.
2063  call term_sendkeys(buf, ":au! TextChanged <buffer> call writefile(['No'], 'Xchanged.txt')\<cr>")
2064  call term_sendkeys(buf, "\<C-\\>\<C-N>:qa!\<cr>")
2065  call WaitForAssert({-> assert_equal('finished', term_getstatus(buf))})
2066  call assert_equal([''], readfile('Xchanged.txt'))
2067
2068  " clean up
2069  call delete('Xchanged.txt')
2070  bwipe!
2071endfunc
2072
2073func Test_autocmd_nested()
2074  let g:did_nested = 0
2075  augroup Testing
2076    au WinNew * edit somefile
2077    au BufNew * let g:did_nested = 1
2078  augroup END
2079  split
2080  call assert_equal(0, g:did_nested)
2081  close
2082  bwipe! somefile
2083
2084  " old nested argument still works
2085  augroup Testing
2086    au!
2087    au WinNew * nested edit somefile
2088    au BufNew * let g:did_nested = 1
2089  augroup END
2090  split
2091  call assert_equal(1, g:did_nested)
2092  close
2093  bwipe! somefile
2094
2095  " New ++nested argument works
2096  augroup Testing
2097    au!
2098    au WinNew * ++nested edit somefile
2099    au BufNew * let g:did_nested = 1
2100  augroup END
2101  split
2102  call assert_equal(1, g:did_nested)
2103  close
2104  bwipe! somefile
2105
2106  augroup Testing
2107    au!
2108  augroup END
2109
2110  call assert_fails('au WinNew * ++nested ++nested echo bad', 'E983:')
2111  call assert_fails('au WinNew * nested nested echo bad', 'E983:')
2112endfunc
2113
2114func Test_autocmd_once()
2115  " Without ++once WinNew triggers twice
2116  let g:did_split = 0
2117  augroup Testing
2118    au WinNew * let g:did_split += 1
2119  augroup END
2120  split
2121  split
2122  call assert_equal(2, g:did_split)
2123  call assert_true(exists('#WinNew'))
2124  close
2125  close
2126
2127  " With ++once WinNew triggers once
2128  let g:did_split = 0
2129  augroup Testing
2130    au!
2131    au WinNew * ++once let g:did_split += 1
2132  augroup END
2133  split
2134  split
2135  call assert_equal(1, g:did_split)
2136  call assert_false(exists('#WinNew'))
2137  close
2138  close
2139
2140  call assert_fails('au WinNew * ++once ++once echo bad', 'E983:')
2141endfunc
2142
2143func Test_autocmd_bufreadpre()
2144  new
2145  let b:bufreadpre = 1
2146  call append(0, range(1000))
2147  w! XAutocmdBufReadPre.txt
2148  autocmd BufReadPre <buffer> :let b:bufreadpre += 1
2149  norm! 500gg
2150  sp
2151  norm! 1000gg
2152  wincmd p
2153  let g:wsv1 = winsaveview()
2154  wincmd p
2155  let g:wsv2 = winsaveview()
2156  " triggers BufReadPre, should not move the cursor in either window
2157  " The topline may change one line in a large window.
2158  edit
2159  call assert_inrange(g:wsv2.topline - 1, g:wsv2.topline + 1, winsaveview().topline)
2160  call assert_equal(g:wsv2.lnum, winsaveview().lnum)
2161  call assert_equal(2, b:bufreadpre)
2162  wincmd p
2163  call assert_equal(g:wsv1.topline, winsaveview().topline)
2164  call assert_equal(g:wsv1.lnum, winsaveview().lnum)
2165  call assert_equal(2, b:bufreadpre)
2166  " Now set the cursor position in an BufReadPre autocommand
2167  " (even though the position will be invalid, this should make Vim reset the
2168  " cursor position in the other window.
2169  wincmd p
2170  set cpo+=g
2171  " won't do anything, but try to set the cursor on an invalid lnum
2172  autocmd BufReadPre <buffer> :norm! 70gg
2173  " triggers BufReadPre, should not move the cursor in either window
2174  e
2175  call assert_equal(1, winsaveview().topline)
2176  call assert_equal(1, winsaveview().lnum)
2177  call assert_equal(3, b:bufreadpre)
2178  wincmd p
2179  call assert_equal(g:wsv1.topline, winsaveview().topline)
2180  call assert_equal(g:wsv1.lnum, winsaveview().lnum)
2181  call assert_equal(3, b:bufreadpre)
2182  close
2183  close
2184  call delete('XAutocmdBufReadPre.txt')
2185  set cpo-=g
2186endfunc
2187
2188" FileChangedShell tested in test_filechanged.vim
2189
2190" Tests for the following autocommands:
2191" - FileWritePre	writing a compressed file
2192" - FileReadPost	reading a compressed file
2193" - BufNewFile		reading a file template
2194" - BufReadPre		decompressing the file to be read
2195" - FilterReadPre	substituting characters in the temp file
2196" - FilterReadPost	substituting characters after filtering
2197" - FileReadPre		set options for decompression
2198" - FileReadPost	decompress the file
2199func Test_ReadWrite_Autocmds()
2200  " Run this test only on Unix-like systems and if gzip is available
2201  CheckUnix
2202  CheckExecutable gzip
2203
2204  " Make $GZIP empty, "-v" would cause trouble.
2205  let $GZIP = ""
2206
2207  " Use a FileChangedShell autocommand to avoid a prompt for 'Xtestfile.gz'
2208  " being modified outside of Vim (noticed on Solaris).
2209  au FileChangedShell * echo 'caught FileChangedShell'
2210
2211  " Test for the FileReadPost, FileWritePre and FileWritePost autocmds
2212  augroup Test1
2213    au!
2214    au FileWritePre    *.gz   '[,']!gzip
2215    au FileWritePost   *.gz   undo
2216    au FileReadPost    *.gz   '[,']!gzip -d
2217  augroup END
2218
2219  new
2220  set bin
2221  call append(0, [
2222	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2223	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2224	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2225	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2226	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2227	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2228	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2229	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2230	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2231	      \ ])
2232  1,9write! Xtestfile.gz
2233  enew! | close
2234
2235  new
2236  " Read and decompress the testfile
2237  0read Xtestfile.gz
2238  call assert_equal([
2239	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2240	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2241	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2242	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2243	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2244	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2245	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2246	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2247	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2248	      \ ], getline(1, 9))
2249  enew! | close
2250
2251  augroup Test1
2252    au!
2253  augroup END
2254
2255  " Test for the FileAppendPre and FileAppendPost autocmds
2256  augroup Test2
2257    au!
2258    au BufNewFile      *.c    read Xtest.c
2259    au FileAppendPre   *.out  '[,']s/new/NEW/
2260    au FileAppendPost  *.out  !cat Xtest.c >> test.out
2261  augroup END
2262
2263  call writefile(['/*', ' * Here is a new .c file', ' */'], 'Xtest.c')
2264  new foo.c			" should load Xtest.c
2265  call assert_equal(['/*', ' * Here is a new .c file', ' */'], getline(2, 4))
2266  w! >> test.out		" append it to the output file
2267
2268  let contents = readfile('test.out')
2269  call assert_equal(' * Here is a NEW .c file', contents[2])
2270  call assert_equal(' * Here is a new .c file', contents[5])
2271
2272  call delete('test.out')
2273  enew! | close
2274  augroup Test2
2275    au!
2276  augroup END
2277
2278  " Test for the BufReadPre and BufReadPost autocmds
2279  augroup Test3
2280    au!
2281    " setup autocommands to decompress before reading and re-compress
2282    " afterwards
2283    au BufReadPre  *.gz  exe '!gzip -d ' . shellescape(expand("<afile>"))
2284    au BufReadPre  *.gz  call rename(expand("<afile>:r"), expand("<afile>"))
2285    au BufReadPost *.gz  call rename(expand("<afile>"), expand("<afile>:r"))
2286    au BufReadPost *.gz  exe '!gzip ' . shellescape(expand("<afile>:r"))
2287  augroup END
2288
2289  e! Xtestfile.gz		" Edit compressed file
2290  call assert_equal([
2291	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2292	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2293	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2294	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2295	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2296	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2297	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2298	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2299	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2300	      \ ], getline(1, 9))
2301
2302  w! >> test.out		" Append it to the output file
2303
2304  augroup Test3
2305    au!
2306  augroup END
2307
2308  " Test for the FilterReadPre and FilterReadPost autocmds.
2309  set shelltemp			" need temp files here
2310  augroup Test4
2311    au!
2312    au FilterReadPre   *.out  call rename(expand("<afile>"), expand("<afile>") . ".t")
2313    au FilterReadPre   *.out  exe 'silent !sed s/e/E/ ' . shellescape(expand("<afile>")) . ".t >" . shellescape(expand("<afile>"))
2314    au FilterReadPre   *.out  exe 'silent !rm ' . shellescape(expand("<afile>")) . '.t'
2315    au FilterReadPost  *.out  '[,']s/x/X/g
2316  augroup END
2317
2318  e! test.out			" Edit the output file
2319  1,$!cat
2320  call assert_equal([
2321	      \ 'linE 2	AbcdefghijklmnopqrstuvwXyz',
2322	      \ 'linE 3	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2323	      \ 'linE 4	AbcdefghijklmnopqrstuvwXyz',
2324	      \ 'linE 5	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2325	      \ 'linE 6	AbcdefghijklmnopqrstuvwXyz',
2326	      \ 'linE 7	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2327	      \ 'linE 8	AbcdefghijklmnopqrstuvwXyz',
2328	      \ 'linE 9	XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
2329	      \ 'linE 10 AbcdefghijklmnopqrstuvwXyz'
2330	      \ ], getline(1, 9))
2331  call assert_equal([
2332	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2333	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2334	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2335	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2336	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2337	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2338	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2339	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2340	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2341	      \ ], readfile('test.out'))
2342
2343  augroup Test4
2344    au!
2345  augroup END
2346  set shelltemp&vim
2347
2348  " Test for the FileReadPre and FileReadPost autocmds.
2349  augroup Test5
2350    au!
2351    au FileReadPre *.gz exe 'silent !gzip -d ' . shellescape(expand("<afile>"))
2352    au FileReadPre *.gz call rename(expand("<afile>:r"), expand("<afile>"))
2353    au FileReadPost *.gz '[,']s/l/L/
2354  augroup END
2355
2356  new
2357  0r Xtestfile.gz		" Read compressed file
2358  call assert_equal([
2359	      \ 'Line 2	Abcdefghijklmnopqrstuvwxyz',
2360	      \ 'Line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2361	      \ 'Line 4	Abcdefghijklmnopqrstuvwxyz',
2362	      \ 'Line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2363	      \ 'Line 6	Abcdefghijklmnopqrstuvwxyz',
2364	      \ 'Line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2365	      \ 'Line 8	Abcdefghijklmnopqrstuvwxyz',
2366	      \ 'Line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2367	      \ 'Line 10 Abcdefghijklmnopqrstuvwxyz'
2368	      \ ], getline(1, 9))
2369  call assert_equal([
2370	      \ 'line 2	Abcdefghijklmnopqrstuvwxyz',
2371	      \ 'line 3	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2372	      \ 'line 4	Abcdefghijklmnopqrstuvwxyz',
2373	      \ 'line 5	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2374	      \ 'line 6	Abcdefghijklmnopqrstuvwxyz',
2375	      \ 'line 7	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2376	      \ 'line 8	Abcdefghijklmnopqrstuvwxyz',
2377	      \ 'line 9	xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx',
2378	      \ 'line 10 Abcdefghijklmnopqrstuvwxyz'
2379	      \ ], readfile('Xtestfile.gz'))
2380
2381  augroup Test5
2382    au!
2383  augroup END
2384
2385  au! FileChangedShell
2386  call delete('Xtestfile.gz')
2387  call delete('Xtest.c')
2388  call delete('test.out')
2389endfunc
2390
2391func Test_throw_in_BufWritePre()
2392  new
2393  call setline(1, ['one', 'two', 'three'])
2394  call assert_false(filereadable('Xthefile'))
2395  augroup throwing
2396    au BufWritePre X* throw 'do not write'
2397  augroup END
2398  try
2399    w Xthefile
2400  catch
2401    let caught = 1
2402  endtry
2403  call assert_equal(1, caught)
2404  call assert_false(filereadable('Xthefile'))
2405
2406  bwipe!
2407  au! throwing
2408endfunc
2409
2410func Test_autocmd_in_try_block()
2411  call mkdir('Xdir')
2412  au BufEnter * let g:fname = expand('%')
2413  try
2414    edit Xdir/
2415  endtry
2416  call assert_match('Xdir', g:fname)
2417
2418  unlet g:fname
2419  au! BufEnter
2420  call delete('Xdir', 'rf')
2421endfunc
2422
2423func Test_autocmd_SafeState()
2424  CheckRunVimInTerminal
2425  let g:test_is_flaky = 1
2426
2427  let lines =<< trim END
2428	let g:safe = 0
2429	let g:again = ''
2430	au SafeState * let g:safe += 1
2431	au SafeStateAgain * let g:again ..= 'x'
2432	func CallTimer()
2433	  call timer_start(10, {id -> execute('let g:again ..= "t"')})
2434	endfunc
2435  END
2436  call writefile(lines, 'XSafeState')
2437  let buf = RunVimInTerminal('-S XSafeState', #{rows: 6})
2438
2439  " Sometimes we loop to handle a K_IGNORE, SafeState may be triggered once or
2440  " more often.
2441  call term_sendkeys(buf, ":echo g:safe\<CR>")
2442  call WaitForAssert({-> assert_match('^\d ', term_getline(buf, 6))}, 1000)
2443
2444  " SafeStateAgain should be invoked at least three times
2445  call term_sendkeys(buf, ":echo g:again\<CR>")
2446  call WaitForAssert({-> assert_match('^xxx', term_getline(buf, 6))}, 1000)
2447
2448  call term_sendkeys(buf, ":let g:again = ''\<CR>:call CallTimer()\<CR>")
2449  call TermWait(buf, 50)
2450  call term_sendkeys(buf, ":\<CR>")
2451  call TermWait(buf, 50)
2452  call term_sendkeys(buf, ":echo g:again\<CR>")
2453  call WaitForAssert({-> assert_match('xtx', term_getline(buf, 6))}, 1000)
2454
2455  call StopVimInTerminal(buf)
2456  call delete('XSafeState')
2457endfunc
2458
2459func Test_autocmd_CmdWinEnter()
2460  CheckRunVimInTerminal
2461  CheckFeature cmdwin
2462
2463  let lines =<< trim END
2464    augroup vimHints | au! | augroup END
2465    let b:dummy_var = 'This is a dummy'
2466    autocmd CmdWinEnter * quit
2467    let winnr = winnr('$')
2468  END
2469  let filename = 'XCmdWinEnter'
2470  call writefile(lines, filename)
2471  let buf = RunVimInTerminal('-S '.filename, #{rows: 6})
2472
2473  call term_sendkeys(buf, "q:")
2474  call TermWait(buf)
2475  call term_sendkeys(buf, ":echo b:dummy_var\<cr>")
2476  call WaitForAssert({-> assert_match('^This is a dummy', term_getline(buf, 6))}, 2000)
2477  call term_sendkeys(buf, ":echo &buftype\<cr>")
2478  call WaitForAssert({-> assert_notmatch('^nofile', term_getline(buf, 6))}, 1000)
2479  call term_sendkeys(buf, ":echo winnr\<cr>")
2480  call WaitForAssert({-> assert_match('^1', term_getline(buf, 6))}, 1000)
2481
2482  " clean up
2483  call StopVimInTerminal(buf)
2484  call delete(filename)
2485endfunc
2486
2487func Test_autocmd_was_using_freed_memory()
2488  CheckFeature quickfix
2489
2490  pedit xx
2491  n x
2492  augroup winenter
2493    au WinEnter * if winnr('$') > 2 | quit | endif
2494  augroup END
2495  split
2496
2497  augroup winenter
2498    au! WinEnter
2499  augroup END
2500
2501  bwipe xx
2502  bwipe x
2503  pclose
2504endfunc
2505
2506func Test_BufWrite_lockmarks()
2507  let g:test_is_flaky = 1
2508  edit! Xtest
2509  call setline(1, ['a', 'b', 'c', 'd'])
2510
2511  " :lockmarks preserves the marks
2512  call SetChangeMarks(2, 3)
2513  lockmarks write
2514  call assert_equal([2, 3], [line("'["), line("']")])
2515
2516  " *WritePre autocmds get the correct line range, but lockmarks preserves the
2517  " original values for the user
2518  augroup lockmarks
2519    au!
2520    au BufWritePre,FilterWritePre * call assert_equal([1, 4], [line("'["), line("']")])
2521    au FileWritePre * call assert_equal([3, 4], [line("'["), line("']")])
2522  augroup END
2523
2524  lockmarks write
2525  call assert_equal([2, 3], [line("'["), line("']")])
2526
2527  if executable('cat')
2528    lockmarks %!cat
2529    call assert_equal([2, 3], [line("'["), line("']")])
2530  endif
2531
2532  lockmarks 3,4write Xtest2
2533  call assert_equal([2, 3], [line("'["), line("']")])
2534
2535  au! lockmarks
2536  augroup! lockmarks
2537  call delete('Xtest')
2538  call delete('Xtest2')
2539endfunc
2540
2541func Test_FileType_spell()
2542  if !isdirectory('/tmp')
2543    throw "Skipped: requires /tmp directory"
2544  endif
2545
2546  " this was crashing with an invalid free()
2547  setglobal spellfile=/tmp/en.utf-8.add
2548  augroup crash
2549    autocmd!
2550    autocmd BufNewFile,BufReadPost crashfile setf somefiletype
2551    autocmd BufNewFile,BufReadPost crashfile set ft=anotherfiletype
2552    autocmd FileType anotherfiletype setlocal spell
2553  augroup END
2554  func! NoCrash() abort
2555    edit /tmp/crashfile
2556  endfunc
2557  call NoCrash()
2558
2559  au! crash
2560  setglobal spellfile=
2561endfunc
2562
2563" Test closing a window or editing another buffer from a FileChangedRO handler
2564" in a readonly buffer
2565func Test_FileChangedRO_winclose()
2566  call test_override('ui_delay', 10)
2567
2568  augroup FileChangedROTest
2569    au!
2570    autocmd FileChangedRO * quit
2571  augroup END
2572  new
2573  set readonly
2574  call assert_fails('normal i', 'E788:')
2575  close
2576  augroup! FileChangedROTest
2577
2578  augroup FileChangedROTest
2579    au!
2580    autocmd FileChangedRO * edit Xfile
2581  augroup END
2582  new
2583  set readonly
2584  call assert_fails('normal i', 'E788:')
2585  close
2586  augroup! FileChangedROTest
2587  call test_override('ALL', 0)
2588endfunc
2589
2590func LogACmd()
2591  call add(g:logged, line('$'))
2592endfunc
2593
2594func Test_TermChanged()
2595  CheckNotGui
2596
2597  enew!
2598  tabnew
2599  call setline(1, ['a', 'b', 'c', 'd'])
2600  $
2601  au TermChanged * call LogACmd()
2602  let g:logged = []
2603  let term_save = &term
2604  set term=xterm
2605  call assert_equal([1, 4], g:logged)
2606
2607  au! TermChanged
2608  let &term = term_save
2609  bwipe!
2610endfunc
2611
2612" Test for FileReadCmd autocmd
2613func Test_autocmd_FileReadCmd()
2614  func ReadFileCmd()
2615    call append(line('$'), "v:cmdarg = " .. v:cmdarg)
2616  endfunc
2617  augroup FileReadCmdTest
2618    au!
2619    au FileReadCmd Xtest call ReadFileCmd()
2620  augroup END
2621
2622  new
2623  read ++bin Xtest
2624  read ++nobin Xtest
2625  read ++edit Xtest
2626  read ++bad=keep Xtest
2627  read ++bad=drop Xtest
2628  read ++bad=- Xtest
2629  read ++ff=unix Xtest
2630  read ++ff=dos Xtest
2631  read ++ff=mac Xtest
2632  read ++enc=utf-8 Xtest
2633
2634  call assert_equal(['',
2635        \ 'v:cmdarg =  ++bin',
2636        \ 'v:cmdarg =  ++nobin',
2637        \ 'v:cmdarg =  ++edit',
2638        \ 'v:cmdarg =  ++bad=keep',
2639        \ 'v:cmdarg =  ++bad=drop',
2640        \ 'v:cmdarg =  ++bad=-',
2641        \ 'v:cmdarg =  ++ff=unix',
2642        \ 'v:cmdarg =  ++ff=dos',
2643        \ 'v:cmdarg =  ++ff=mac',
2644        \ 'v:cmdarg =  ++enc=utf-8'], getline(1, '$'))
2645
2646  close!
2647  augroup FileReadCmdTest
2648    au!
2649  augroup END
2650  delfunc ReadFileCmd
2651endfunc
2652
2653" Test for passing invalid arguments to autocmd
2654func Test_autocmd_invalid_args()
2655  " Additional character after * for event
2656  call assert_fails('autocmd *a Xfile set ff=unix', 'E215:')
2657  augroup Test
2658  augroup END
2659  " Invalid autocmd event
2660  call assert_fails('autocmd Bufabc Xfile set ft=vim', 'E216:')
2661  " Invalid autocmd event in a autocmd group
2662  call assert_fails('autocmd Test Bufabc Xfile set ft=vim', 'E216:')
2663  augroup! Test
2664  " Execute all autocmds
2665  call assert_fails('doautocmd * BufEnter', 'E217:')
2666  call assert_fails('augroup! x1a2b3', 'E367:')
2667  call assert_fails('autocmd BufNew <buffer=999> pwd', 'E680:')
2668  call assert_fails('autocmd BufNew \) set ff=unix', 'E55:')
2669endfunc
2670
2671" Test for deep nesting of autocmds
2672func Test_autocmd_deep_nesting()
2673  autocmd BufEnter Xfile doautocmd BufEnter Xfile
2674  call assert_fails('doautocmd BufEnter Xfile', 'E218:')
2675  autocmd! BufEnter Xfile
2676endfunc
2677
2678" Tests for SigUSR1 autocmd event, which is only available on posix systems.
2679func Test_autocmd_sigusr1()
2680  CheckUnix
2681  CheckExecutable /bin/kill
2682
2683  let g:sigusr1_passed = 0
2684  au SigUSR1 * let g:sigusr1_passed = 1
2685  call system('/bin/kill -s usr1 ' . getpid())
2686  call WaitForAssert({-> assert_true(g:sigusr1_passed)})
2687
2688  au! SigUSR1
2689  unlet g:sigusr1_passed
2690endfunc
2691
2692" Test for BufReadPre autocmd deleting the file
2693func Test_BufReadPre_delfile()
2694  augroup TestAuCmd
2695    au!
2696    autocmd BufReadPre Xfile call delete('Xfile')
2697  augroup END
2698  call writefile([], 'Xfile')
2699  call assert_fails('new Xfile', 'E200:')
2700  call assert_equal('Xfile', @%)
2701  call assert_equal(1, &readonly)
2702  call delete('Xfile')
2703  augroup TestAuCmd
2704    au!
2705  augroup END
2706  close!
2707endfunc
2708
2709" Test for BufReadPre autocmd changing the current buffer
2710func Test_BufReadPre_changebuf()
2711  augroup TestAuCmd
2712    au!
2713    autocmd BufReadPre Xfile edit Xsomeotherfile
2714  augroup END
2715  call writefile([], 'Xfile')
2716  call assert_fails('new Xfile', 'E201:')
2717  call assert_equal('Xsomeotherfile', @%)
2718  call assert_equal(1, &readonly)
2719  call delete('Xfile')
2720  augroup TestAuCmd
2721    au!
2722  augroup END
2723  close!
2724endfunc
2725
2726" Test for BufWipeouti autocmd changing the current buffer when reading a file
2727" in an empty buffer with 'f' flag in 'cpo'
2728func Test_BufDelete_changebuf()
2729  new
2730  augroup TestAuCmd
2731    au!
2732    autocmd BufWipeout * let bufnr = bufadd('somefile') | exe "b " .. bufnr
2733  augroup END
2734  let save_cpo = &cpo
2735  set cpo+=f
2736  call assert_fails('r Xfile', ['E812:', 'E484:'])
2737  call assert_equal('somefile', @%)
2738  let &cpo = save_cpo
2739  augroup TestAuCmd
2740    au!
2741  augroup END
2742  close!
2743endfunc
2744
2745" Test for the temporary internal window used to execute autocmds
2746func Test_autocmd_window()
2747  %bw!
2748  edit one.txt
2749  tabnew two.txt
2750  vnew three.txt
2751  tabnew four.txt
2752  tabprevious
2753  let g:blist = []
2754  augroup aucmd_win_test1
2755    au!
2756    au BufEnter * call add(g:blist, [expand('<afile>'),
2757          \ win_gettype(bufwinnr(expand('<afile>')))])
2758  augroup END
2759
2760  doautoall BufEnter
2761  call assert_equal([
2762        \ ['one.txt', 'autocmd'],
2763        \ ['two.txt', ''],
2764        \ ['four.txt', 'autocmd'],
2765        \ ['three.txt', ''],
2766        \ ], g:blist)
2767
2768  augroup aucmd_win_test1
2769    au!
2770  augroup END
2771  augroup! aucmd_win_test1
2772  %bw!
2773endfunc
2774
2775" Test for trying to close the temporary window used for executing an autocmd
2776func Test_close_autocmd_window()
2777  %bw!
2778  edit one.txt
2779  tabnew two.txt
2780  augroup aucmd_win_test2
2781    au!
2782    au BufEnter * if expand('<afile>') == 'one.txt' | 1close | endif
2783  augroup END
2784
2785  call assert_fails('doautoall BufEnter', 'E813:')
2786
2787  augroup aucmd_win_test2
2788    au!
2789  augroup END
2790  augroup! aucmd_win_test2
2791  %bwipe!
2792endfunc
2793
2794" Test for trying to close the tab that has the temporary window for exeucing
2795" an autocmd.
2796func Test_close_autocmd_tab()
2797  edit one.txt
2798  tabnew two.txt
2799   augroup aucmd_win_test
2800    au!
2801    au BufEnter * if expand('<afile>') == 'one.txt' | tabfirst | tabonly | endif
2802  augroup END
2803
2804  call assert_fails('doautoall BufEnter', 'E813:')
2805
2806  tabonly
2807  augroup aucmd_win_test
2808    au!
2809  augroup END
2810  augroup! aucmd_win_test
2811  %bwipe!
2812endfunc
2813
2814" This was using freed memory.
2815func Test_BufNew_arglocal()
2816  arglocal
2817  au BufNew * arglocal
2818  call assert_fails('drop xx', 'E1156:')
2819
2820  au! BufNew
2821endfunc
2822
2823func Test_autocmd_closes_window()
2824  au BufNew,BufWinLeave * e %e
2825  file yyy
2826  au BufNew,BufWinLeave * ball
2827  n xxx
2828
2829  %bwipe
2830  au! BufNew
2831  au! BufWinLeave
2832endfunc
2833
2834func Test_autocmd_quit_psearch()
2835  sn aa bb
2836  augroup aucmd_win_test
2837    au!
2838    au BufEnter,BufLeave,BufNew,WinEnter,WinLeave,WinNew * if winnr('$') > 1 | q | endif
2839  augroup END
2840  ps /
2841
2842  augroup aucmd_win_test
2843    au!
2844  augroup END
2845endfunc
2846
2847" Fuzzer found some strange combination that caused a crash.
2848func Test_autocmd_normal_mess()
2849  " For unknown reason this hangs on MS-Windows
2850  CheckNotMSWindows
2851
2852  augroup aucmd_normal_test
2853    au BufLeave,BufWinLeave,BufHidden,BufUnload,BufDelete,BufWipeout * norm 7q/qc
2854  augroup END
2855  call assert_fails('o4', 'E1159')
2856  silent! H
2857  call assert_fails('e xx', 'E1159')
2858  normal G
2859
2860  augroup aucmd_normal_test
2861    au!
2862  augroup END
2863endfunc
2864
2865func Test_autocmd_closing_cmdwin()
2866  " For unknown reason this hangs on MS-Windows
2867  CheckNotMSWindows
2868
2869  au BufWinLeave * nested q
2870  call assert_fails("norm 7q?\n", 'E855:')
2871
2872  au! BufWinLeave
2873  new
2874  only
2875endfunc
2876
2877func Test_autocmd_vimgrep()
2878  augroup aucmd_vimgrep
2879    au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * sb
2880    au QuickfixCmdPre,BufNew,BufDelete,BufReadCmd * q9�
2881  augroup END
2882  %bwipe!
2883  call assert_fails('lv ?a? foo', 'E926:')
2884
2885  augroup aucmd_vimgrep
2886    au!
2887  augroup END
2888endfunc
2889
2890func Test_autocmd_with_block()
2891  augroup block_testing
2892    au BufReadPost *.xml {
2893            setlocal matchpairs+=<:>
2894            /<start
2895          }
2896    au CursorHold * {
2897        autocmd BufReadPre * ++once echo 'one' | echo 'two'
2898        g:gotSafeState = 77
2899      }
2900  augroup END
2901
2902  let expected = "\n--- Autocommands ---\nblock_testing  BufRead\n    *.xml     {^@            setlocal matchpairs+=<:>^@            /<start^@          }"
2903  call assert_equal(expected, execute('au BufReadPost *.xml'))
2904
2905  doautocmd CursorHold
2906  call assert_equal(77, g:gotSafeState)
2907  unlet g:gotSafeState
2908
2909  augroup block_testing
2910    au!
2911  augroup END
2912endfunc
2913
2914" Test TextChangedI and TextChanged
2915func Test_Changed_ChangedI()
2916  new
2917  call test_override("char_avail", 1)
2918  let [g:autocmd_i, g:autocmd_n] = ['','']
2919
2920  func! TextChangedAutocmdI(char)
2921    let g:autocmd_{tolower(a:char)} = a:char .. b:changedtick
2922  endfunc
2923
2924  augroup Test_TextChanged
2925    au!
2926    au TextChanged  <buffer> :call TextChangedAutocmdI('N')
2927    au TextChangedI <buffer> :call TextChangedAutocmdI('I')
2928  augroup END
2929
2930  call feedkeys("ifoo\<esc>", 'tnix')
2931  " TODO: Test test does not seem to trigger TextChanged autocommand, this
2932  " requires running Vim in a terminal window.
2933  " call assert_equal('N3', g:autocmd_n)
2934  call assert_equal('I3', g:autocmd_i)
2935
2936  call feedkeys("yyp", 'tnix')
2937  " TODO: Test test does not seem to trigger TextChanged autocommand.
2938  " call assert_equal('N4', g:autocmd_n)
2939  call assert_equal('I3', g:autocmd_i)
2940
2941  " CleanUp
2942  call test_override("char_avail", 0)
2943  au! TextChanged  <buffer>
2944  au! TextChangedI <buffer>
2945  augroup! Test_TextChanged
2946  delfu TextChangedAutocmdI
2947  unlet! g:autocmd_i g:autocmd_n
2948
2949  bw!
2950endfunc
2951
2952" vim: shiftwidth=2 sts=2 expandtab
2953