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