test_buffer.vim (24649B)
1 " Tests for Vim buffer 2 3 source check.vim 4 5 " Test for the :bunload command with an offset 6 func Test_bunload_with_offset() 7 %bwipe! 8 call writefile(['B1'], 'Xb1', 'D') 9 call writefile(['B2'], 'Xb2', 'D') 10 call writefile(['B3'], 'Xb3', 'D') 11 call writefile(['B4'], 'Xb4', 'D') 12 13 " Load four buffers. Unload the second and third buffers and then 14 " execute .+3bunload to unload the last buffer. 15 edit Xb1 16 new Xb2 17 new Xb3 18 new Xb4 19 20 bunload Xb2 21 bunload Xb3 22 exe bufwinnr('Xb1') . 'wincmd w' 23 .+3bunload 24 call assert_equal(0, getbufinfo('Xb4')[0].loaded) 25 call assert_equal('Xb1', 26 \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) 27 28 " Load four buffers. Unload the third and fourth buffers. Execute .+3bunload 29 " and check whether the second buffer is unloaded. 30 ball 31 bunload Xb3 32 bunload Xb4 33 exe bufwinnr('Xb1') . 'wincmd w' 34 .+3bunload 35 call assert_equal(0, getbufinfo('Xb2')[0].loaded) 36 call assert_equal('Xb1', 37 \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) 38 39 " Load four buffers. Unload the second and third buffers and from the last 40 " buffer execute .-3bunload to unload the first buffer. 41 ball 42 bunload Xb2 43 bunload Xb3 44 exe bufwinnr('Xb4') . 'wincmd w' 45 .-3bunload 46 call assert_equal(0, getbufinfo('Xb1')[0].loaded) 47 call assert_equal('Xb4', 48 \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) 49 50 " Load four buffers. Unload the first and second buffers. Execute .-3bunload 51 " from the last buffer and check whether the third buffer is unloaded. 52 ball 53 bunload Xb1 54 bunload Xb2 55 exe bufwinnr('Xb4') . 'wincmd w' 56 .-3bunload 57 call assert_equal(0, getbufinfo('Xb3')[0].loaded) 58 call assert_equal('Xb4', 59 \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t')) 60 61 %bwipe! 62 63 call assert_fails('1,4bunload', 'E16:') 64 call assert_fails(',100bunload', 'E16:') 65 66 call assert_fails('$bunload', 'E90:') 67 endfunc 68 69 " Test for :buffer, :bnext, :bprevious, :brewind, :blast and :bmodified 70 " commands 71 func Test_buflist_browse() 72 %bwipe! 73 call assert_fails('buffer 1000', 'E86:') 74 75 call writefile(['foo1', 'foo2', 'foo3', 'foo4'], 'Xbrowse1', 'D') 76 call writefile(['bar1', 'bar2', 'bar3', 'bar4'], 'Xbrowse2', 'D') 77 call writefile(['baz1', 'baz2', 'baz3', 'baz4'], 'Xbrowse3', 'D') 78 edit Xbrowse1 79 let b1 = bufnr() 80 edit Xbrowse2 81 let b2 = bufnr() 82 edit +/baz4 Xbrowse3 83 let b3 = bufnr() 84 85 call assert_fails('buffer ' .. b1 .. ' abc', 'E488:') 86 call assert_equal(b3, bufnr()) 87 call assert_equal(4, line('.')) 88 exe 'buffer +/bar2 ' .. b2 89 call assert_equal(b2, bufnr()) 90 call assert_equal(2, line('.')) 91 exe 'buffer +/bar1' 92 call assert_equal(b2, bufnr()) 93 call assert_equal(1, line('.')) 94 95 brewind + 96 call assert_equal(b1, bufnr()) 97 call assert_equal(4, line('.')) 98 99 blast +/baz2 100 call assert_equal(b3, bufnr()) 101 call assert_equal(2, line('.')) 102 103 bprevious +/bar4 104 call assert_equal(b2, bufnr()) 105 call assert_equal(4, line('.')) 106 107 bnext +/baz3 108 call assert_equal(b3, bufnr()) 109 call assert_equal(3, line('.')) 110 111 call assert_fails('bmodified', 'E84:') 112 call setbufvar(b2, '&modified', 1) 113 exe 'bmodified +/bar3' 114 call assert_equal(b2, bufnr()) 115 call assert_equal(3, line('.')) 116 117 " With no listed buffers in the list, :bnext and :bprev should fail 118 %bwipe! 119 set nobuflisted 120 call assert_fails('bnext', 'E85:') 121 call assert_fails('bprev', 'E85:') 122 set buflisted 123 124 call assert_fails('sandbox bnext', 'E48:') 125 126 %bwipe! 127 endfunc 128 129 " Test for :bnext and :bprev when called from help and non-help buffers. 130 func Test_bnext_bprev_help() 131 %bwipe! 132 133 e XHelp1 | set bt=help 134 let b1 = bufnr() 135 e Xbuf1 136 let b2 = bufnr() 137 138 " There's only one buffer of each type. 139 b XHelp1 140 bnext | call assert_equal(b1, bufnr()) 141 bprev | call assert_equal(b1, bufnr()) 142 b Xbuf1 143 bnext | call assert_equal(b2, bufnr()) 144 bprev | call assert_equal(b2, bufnr()) 145 146 " Add one more buffer of each type. 147 e XHelp2 | set bt=help 148 let b3 = bufnr() 149 e Xbuf2 150 let b4 = bufnr() 151 152 " Help buffer jumps to help buffer. 153 b XHelp1 154 bnext | call assert_equal(b3, bufnr()) 155 bnext | call assert_equal(b1, bufnr()) 156 bprev | call assert_equal(b3, bufnr()) 157 bprev | call assert_equal(b1, bufnr()) 158 159 " Regular buffer jumps to regular buffer. 160 b Xbuf1 161 bnext | call assert_equal(b4, bufnr()) 162 bnext | call assert_equal(b2, bufnr()) 163 bprev | call assert_equal(b4, bufnr()) 164 bprev | call assert_equal(b2, bufnr()) 165 166 " :brewind and :blast are not affected by the buffer type. 167 b Xbuf2 168 brewind | call assert_equal(b1, bufnr()) 169 b XHelp1 170 blast | call assert_equal(b4, bufnr()) 171 172 " Cycling through help buffers works even if they aren't listed. 173 b XHelp1 174 setlocal nobuflisted 175 bnext | call assert_equal(b3, bufnr()) 176 bnext | call assert_equal(b1, bufnr()) 177 bprev | call assert_equal(b3, bufnr()) 178 setlocal nobuflisted 179 bprev | call assert_equal(b1, bufnr()) 180 bprev | call assert_equal(b3, bufnr()) 181 bnext | call assert_equal(b1, bufnr()) 182 183 %bwipe! 184 endfunc 185 186 " Test for :bdelete 187 func Test_bdelete_cmd() 188 %bwipe! 189 call assert_fails('bdelete 5', 'E516:') 190 call assert_fails('1,1bdelete 1 2', 'E488:') 191 call assert_fails('bdelete \)', 'E55:') 192 193 " Deleting an unlisted and unloaded buffer 194 edit Xbdelfile1 195 let bnr = bufnr() 196 set nobuflisted 197 enew 198 call assert_fails('bdelete ' .. bnr, 'E516:') 199 200 " Deleting more than one buffer 201 new Xbuf1 202 new Xbuf2 203 exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1') 204 call assert_equal(1, winnr('$')) 205 call assert_equal(0, getbufinfo('Xbuf1')[0].loaded) 206 call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) 207 208 " Deleting more than one buffer and an invalid buffer 209 new Xbuf1 210 new Xbuf2 211 let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')" 212 call assert_fails(cmd, 'E94:') 213 call assert_equal(2, winnr('$')) 214 call assert_equal(1, getbufinfo('Xbuf1')[0].loaded) 215 call assert_equal(0, getbufinfo('Xbuf2')[0].loaded) 216 217 %bwipe! 218 endfunc 219 220 func Test_buffer_error() 221 new foo1 222 new foo2 223 224 call assert_fails('buffer foo', 'E93:') 225 call assert_fails('buffer bar', 'E94:') 226 call assert_fails('buffer 0', 'E939:') 227 228 %bwipe 229 endfunc 230 231 func Test_bwipe_during_save() 232 set charconvert=execute('%bw!') 233 call assert_fails('write ++enc=lmao boom', 'E937:') 234 235 set charconvert& 236 %bwipe 237 endfunc 238 239 " Test for the status messages displayed when unloading, deleting or wiping 240 " out buffers 241 func Test_buffer_statusmsg() 242 CheckEnglish 243 set report=1 244 new Xbuf1 245 new Xbuf2 246 let bnr = bufnr() 247 exe "normal 2\<C-G>" 248 call assert_match('buf ' .. bnr .. ':', v:statusmsg) 249 bunload Xbuf1 Xbuf2 250 call assert_equal('2 buffers unloaded', v:statusmsg) 251 bdel Xbuf1 Xbuf2 252 call assert_equal('2 buffers deleted', v:statusmsg) 253 bwipe Xbuf1 Xbuf2 254 call assert_equal('2 buffers wiped out', v:statusmsg) 255 set report& 256 endfunc 257 258 " Test for quitting the 'swapfile exists' dialog with the split buffer 259 " command. 260 func Test_buffer_sbuf_cleanup() 261 call writefile([], 'XsplitCleanup', 'D') 262 " first open the file in a buffer 263 new XsplitCleanup 264 let bnr = bufnr() 265 close 266 " create the swap file 267 call writefile([], '.XsplitCleanup.swp', 'D') 268 " Remove the catch-all that runtest.vim adds 269 au! SwapExists 270 augroup BufTest 271 au! 272 autocmd SwapExists XsplitCleanup let v:swapchoice='q' 273 augroup END 274 exe 'sbuf ' . bnr 275 call assert_equal(1, winnr('$')) 276 call assert_equal(0, getbufinfo('XsplitCleanup')[0].loaded) 277 278 " test for :sball 279 sball 280 call assert_equal(1, winnr('$')) 281 call assert_equal(0, getbufinfo('XsplitCleanup')[0].loaded) 282 283 %bw! 284 set shortmess+=F 285 let v:statusmsg = '' 286 edit XsplitCleanup 287 call assert_equal('', v:statusmsg) 288 call assert_equal(1, winnr('$')) 289 call assert_equal(0, getbufinfo('XsplitCleanup')[0].loaded) 290 set shortmess& 291 292 augroup BufTest 293 au! 294 augroup END 295 augroup! BufTest 296 endfunc 297 298 " Test for deleting a modified buffer with :confirm 299 func Test_bdel_with_confirm() 300 CheckUnix 301 CheckNotGui 302 CheckFeature dialog_con 303 new 304 call setline(1, 'test') 305 call assert_fails('bdel', 'E89:') 306 call feedkeys('c', 'L') 307 confirm bdel 308 call assert_equal(2, winnr('$')) 309 call assert_equal(1, &modified) 310 call feedkeys('n', 'L') 311 confirm bdel 312 call assert_equal(1, winnr('$')) 313 endfunc 314 315 " Test for editing another buffer from a modified buffer with :confirm 316 func Test_goto_buf_with_confirm() 317 CheckUnix 318 CheckNotGui 319 CheckFeature dialog_con 320 " When dialog_con_gui is defined, Vim is compiled with GUI support 321 " and FEAT_BROWSE will be defined, which causes :confirm :b to 322 " call do_browse(), which will try to use a GUI file browser, 323 " which aborts if a GUI is not available. 324 CheckNotFeature dialog_con_gui 325 new XgotoConf 326 enew 327 call setline(1, 'test') 328 call assert_fails('b XgotoConf', 'E37:') 329 call feedkeys('c', 'L') 330 call assert_fails('confirm b XgotoConf', 'E37:') 331 call assert_true(&modified) 332 call assert_true(empty(bufname('%'))) 333 call feedkeys('y', 'L') 334 confirm b XgotoConf 335 call assert_equal('XgotoConf', bufname('%')) 336 call assert_equal(['test'], readfile('Untitled')) 337 e Untitled 338 call setline(2, 'test2') 339 call feedkeys('n', 'L') 340 confirm b XgotoConf 341 call assert_equal('XgotoConf', bufname('%')) 342 call assert_equal(['test'], readfile('Untitled')) 343 call delete('Untitled') 344 close! 345 endfunc 346 347 " Test for splitting buffer with 'switchbuf' 348 func Test_buffer_switchbuf() 349 new Xswitchbuf 350 wincmd w 351 set switchbuf=useopen 352 sbuf Xswitchbuf 353 call assert_equal(1, winnr()) 354 call assert_equal(2, winnr('$')) 355 set switchbuf=usetab 356 tabnew 357 sbuf Xswitchbuf 358 call assert_equal(1, tabpagenr()) 359 call assert_equal(2, tabpagenr('$')) 360 set switchbuf& 361 %bw 362 endfunc 363 364 " Test for BufAdd autocommand wiping out the buffer 365 func Test_bufadd_autocmd_bwipe() 366 %bw! 367 augroup BufAdd_Wipe 368 au! 369 autocmd BufAdd Xbwipe %bw! 370 augroup END 371 edit Xbwipe 372 call assert_equal('', @%) 373 call assert_equal(0, bufexists('Xbwipe')) 374 augroup BufAdd_Wipe 375 au! 376 augroup END 377 augroup! BufAdd_Wipe 378 endfunc 379 380 " Test for trying to load a buffer with text locked 381 " <C-\>e in the command line is used to lock the text 382 func Test_load_buf_with_text_locked() 383 new Xlockfile1 384 edit Xlockfile2 385 let cmd = ":\<C-\>eexecute(\"normal \<C-O>\")\<CR>\<C-C>" 386 call assert_fails("call feedkeys(cmd, 'xt')", 'E565:') 387 %bw! 388 endfunc 389 390 " Test for using CTRL-^ to edit the alternative file keeping the cursor 391 " position with 'nostartofline'. Also test using the 'buf' command. 392 func Test_buffer_edit_altfile() 393 call writefile(repeat(['one two'], 50), 'Xaltfile1', 'D') 394 call writefile(repeat(['five six'], 50), 'Xaltfile2', 'D') 395 set nosol 396 edit Xaltfile1 397 call cursor(25, 5) 398 edit Xaltfile2 399 call cursor(30, 4) 400 exe "normal \<C-^>" 401 call assert_equal([0, 25, 5, 0], getpos('.')) 402 exe "normal \<C-^>" 403 call assert_equal([0, 30, 4, 0], getpos('.')) 404 buf Xaltfile1 405 call assert_equal([0, 25, 5, 0], getpos('.')) 406 buf Xaltfile2 407 call assert_equal([0, 30, 4, 0], getpos('.')) 408 set sol& 409 endfunc 410 411 " Test for running the :sball command with a maximum window count and a 412 " modified buffer 413 func Test_sball_with_count() 414 %bw! 415 edit Xcountfile1 416 call setline(1, ['abc']) 417 new Xcountfile2 418 new Xcountfile3 419 new Xcountfile4 420 2sball 421 call assert_equal(bufnr('Xcountfile4'), winbufnr(1)) 422 call assert_equal(bufnr('Xcountfile1'), winbufnr(2)) 423 call assert_equal(0, getbufinfo('Xcountfile2')[0].loaded) 424 call assert_equal(0, getbufinfo('Xcountfile3')[0].loaded) 425 %bw! 426 endfunc 427 428 func Test_badd_options() 429 new SomeNewBuffer 430 setlocal numberwidth=3 431 wincmd p 432 badd +1 SomeNewBuffer 433 new SomeNewBuffer 434 call assert_equal(3, &numberwidth) 435 close 436 close 437 bwipe! SomeNewBuffer 438 endfunc 439 440 func Test_balt() 441 new SomeNewBuffer 442 balt +3 OtherBuffer 443 e # 444 call assert_equal('OtherBuffer', bufname()) 445 endfunc 446 447 " Test for buffer match URL(scheme) check 448 " scheme is alpha and inner hyphen only. 449 func Test_buffer_scheme() 450 CheckMSWindows 451 452 set noswapfile 453 set noshellslash 454 %bwipe! 455 let bufnames = [ 456 \ #{id: 'ssb0' , name: 'test://xyz/foo/ssb0' , match: 1}, 457 \ #{id: 'ssb1' , name: 'test1234://xyz/foo/ssb1', match: 1}, 458 \ #{id: 'ssb2' , name: 'test+abc://xyz/foo/ssb2', match: 1}, 459 \ #{id: 'ssb3' , name: 'test-abc://xyz/foo/ssb3', match: 1}, 460 \ #{id: 'ssb4' , name: 'test.abc://xyz/foo/ssb4', match: 1}, 461 \ #{id: 'ssb5' , name: 'test_abc://xyz/foo/ssb5', match: 0}, 462 \ #{id: 'ssb6' , name: '+test://xyz/foo/ssb6' , match: 0}, 463 \ #{id: 'ssb7' , name: 'test+://xyz/foo/ssb7' , match: 0}, 464 \ #{id: 'ssb8' , name: '-test://xyz/foo/ssb8' , match: 0}, 465 \ #{id: 'ssb9' , name: 'test-://xyz/foo/ssb9' , match: 0}, 466 \ #{id: 'ssb10', name: '.test://xyz/foo/ssb10' , match: 0}, 467 \ #{id: 'ssb11', name: 'test.://xyz/foo/ssb11' , match: 0}, 468 \] 469 for buf in bufnames 470 new `=buf.name` 471 if buf.match 472 call assert_equal(buf.name, getbufinfo(buf.id)[0].name) 473 else 474 " slashes will have become backslashes 475 call assert_notequal(buf.name, getbufinfo(buf.id)[0].name) 476 endif 477 bwipe 478 endfor 479 480 set shellslash& 481 set swapfile& 482 endfunc 483 484 " this was using a NULL pointer after failing to use the pattern 485 func Test_buf_pattern_invalid() 486 vsplit 0000000 487 silent! buf [0--]\&\zs*\zs*e 488 bwipe! 489 490 vsplit 00000000000000000000000000 491 silent! buf [0--]\&\zs*\zs*e 492 bwipe! 493 494 " similar case with different code path 495 split 0 496 edit ΓΏ 497 silent! buf [0--]\&\zs*\zs*0 498 bwipe! 499 endfunc 500 501 " Test for the 'maxmem' and 'maxmemtot' options 502 func Test_buffer_maxmem() 503 " use 1KB per buffer and 2KB for all the buffers 504 " set maxmem=1 maxmemtot=2 505 new 506 let v:errmsg = '' 507 " try opening some files 508 edit test_arglist.vim 509 call assert_equal('test_arglist.vim', bufname()) 510 edit test_eval_stuff.vim 511 call assert_equal('test_eval_stuff.vim', bufname()) 512 b test_arglist.vim 513 call assert_equal('test_arglist.vim', bufname()) 514 b test_eval_stuff.vim 515 call assert_equal('test_eval_stuff.vim', bufname()) 516 close 517 call assert_equal('', v:errmsg) 518 " set maxmem& maxmemtot& 519 endfunc 520 521 " Test for buffer allocation failure 522 func Test_buflist_alloc_failure() 523 CheckFunction test_alloc_fail 524 %bw! 525 526 edit XallocFail1 527 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 528 call assert_fails('edit XallocFail2', 'E342:') 529 530 " test for bufadd() 531 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 532 call assert_fails('call bufadd("Xbuffer")', 'E342:') 533 534 " test for setting the arglist 535 edit XallocFail2 536 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 537 call assert_fails('next XallocFail3', 'E342:') 538 539 " test for setting the alternate buffer name when writing a file 540 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 541 call assert_fails('write Xother', 'E342:') 542 call delete('Xother') 543 544 " test for creating a buffer using bufnr() 545 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 546 call assert_fails("call bufnr('Xnewbuf', v:true)", 'E342:') 547 548 " test for renaming buffer using :file 549 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 550 call assert_fails('file Xnewfile', 'E342:') 551 552 " test for creating a buffer for a popup window 553 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 554 call assert_fails('call popup_create("mypop", {})', 'E342:') 555 556 if has('terminal') 557 " test for creating a buffer for a terminal window 558 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 559 call assert_fails('call term_start(&shell)', 'E342:') 560 %bw! 561 endif 562 563 " test for loading a new buffer after wiping out all the buffers 564 edit XallocFail4 565 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 566 call assert_fails('%bw!', 'E342:') 567 568 " test for :checktime loading the buffer 569 call writefile(['one'], 'XallocFail5', 'D') 570 if has('unix') 571 edit XallocFail5 572 " sleep for some time to make sure the timestamp is different 573 sleep 200m 574 call writefile(['two'], 'XallocFail5') 575 set autoread 576 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 577 call assert_fails('checktime', 'E342:') 578 set autoread& 579 bw! 580 endif 581 582 " test for :vimgrep loading a dummy buffer 583 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 584 call assert_fails('vimgrep two XallocFail5', 'E342:') 585 586 " test for quickfix command loading a buffer 587 call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0) 588 call assert_fails('cexpr "XallocFail6:10:Line10"', 'E342:') 589 endfunc 590 591 func Test_closed_buffer_still_in_window() 592 %bw! 593 594 let s:fired = 0 595 let s:w = win_getid() 596 new 597 let s:b = bufnr() 598 setl bufhidden=wipe 599 augroup ViewClosedBuffer 600 autocmd! 601 autocmd BufUnload * ++once let s:fired += 1 | call assert_fails( 602 \ 'call win_execute(s:w, "' .. s:b .. 'buffer")', 'E1546:') 603 augroup END 604 quit! 605 " Previously resulted in s:b being curbuf while unloaded (no memfile). 606 call assert_equal(1, s:fired) 607 call assert_equal(1, bufloaded(bufnr())) 608 call assert_equal(0, bufexists(s:b)) 609 %bw! 610 611 new flobby 612 let s:w = win_getid() 613 let s:b = bufnr() 614 setl bufhidden=wipe 615 augroup ViewClosedBuffer 616 autocmd! 617 autocmd BufUnload * ++once let s:fired += 1 618 \| wincmd p 619 \| call assert_notequal(s:w, win_getid()) 620 \| call assert_notequal(s:b, bufnr()) 621 \| execute s:b 'sbuffer' 622 \| call assert_equal(s:w, win_getid()) 623 \| call assert_equal(s:b, bufnr()) 624 augroup END 625 " Not a problem if 'switchbuf' switches to an existing window instead. 626 set switchbuf=useopen 627 quit! 628 call assert_equal(2, s:fired) 629 call assert_equal(0, bufexists(s:b)) 630 set switchbuf& 631 %bw! 632 633 edit floob 634 let s:b = bufnr() 635 enew 636 augroup ViewClosedBuffer 637 autocmd! 638 autocmd BufWipeout * ++once let s:fired += 1 639 \| call assert_fails(s:b .. 'sbuffer | wincmd p', 'E1546:') 640 \| call assert_equal(1, winnr('$')) " :sbuffer shouldn't have split. 641 augroup END 642 " Used to be a heap UAF. 643 execute s:b 'bwipeout!' 644 call assert_equal(3, s:fired) 645 call assert_equal(0, bufexists(s:b)) 646 %bw! 647 648 edit flarb 649 let s:b = bufnr() 650 enew 651 let b2 = bufnr() 652 augroup ViewClosedBuffer 653 autocmd! 654 autocmd BufWipeout * ++once let s:fired += 1 655 \| call assert_fails(s:b .. 'sbuffer', 'E1159:') 656 augroup END 657 " :sbuffer still should fail if curbuf is closing, even if it's not the target 658 " buffer (as switching buffers can fail after the split) 659 bwipeout! 660 call assert_equal(4, s:fired) 661 call assert_equal(0, bufexists(b2)) 662 %bw! 663 664 let s:w = win_getid() 665 split 666 new 667 let s:b = bufnr() 668 augroup ViewClosedBuffer 669 autocmd! 670 autocmd BufWipeout * ++once let s:fired += 1 | call win_gotoid(s:w) 671 \| call assert_fails(s:b .. 'buffer', 'E1546:') | wincmd p 672 augroup END 673 bw! " Close only this buffer first; used to be a heap UAF. 674 call assert_equal(5, s:fired) 675 676 unlet! s:w s:b s:fired 677 autocmd! ViewClosedBuffer 678 %bw! 679 endfunc 680 681 " Cursor position should be restored when switching to a buffer previously 682 " viewed in a window, regardless of whether it's visible in another one. 683 func Test_switch_to_previously_viewed_buffer() 684 set nostartofline 685 new Xviewbuf 686 call setline(1, range(1, 200)) 687 let oldwin = win_getid() 688 vsplit 689 690 call cursor(100, 3) 691 call assert_equal('100', getline('.')) 692 edit Xotherbuf 693 buffer Xviewbuf 694 call assert_equal([0, 100, 3, 0], getpos('.')) 695 call assert_equal('100', getline('.')) 696 697 edit Xotherbuf 698 wincmd p 699 normal! gg10dd 700 wincmd p 701 buffer Xviewbuf 702 call assert_equal([0, 90, 3, 0], getpos('.')) 703 call assert_equal('100', getline('.')) 704 705 edit Xotherbuf 706 wincmd p 707 normal! ggP 708 wincmd p 709 buffer Xviewbuf 710 call assert_equal([0, 100, 3, 0], getpos('.')) 711 call assert_equal('100', getline('.')) 712 713 edit Xotherbuf 714 wincmd p 715 normal! 96gg10ddgg 716 wincmd p 717 buffer Xviewbuf 718 " The original cursor line was deleted, so cursor is restored to the start 719 " of the line before the deleted range. 720 call assert_equal([0, 95, 1, 0], getpos('.')) 721 call assert_equal('95', getline('.')) 722 723 normal! u 724 exe win_id2win(oldwin) .. 'close' 725 setlocal bufhidden=hide 726 727 call cursor(200, 3) 728 call assert_equal('200', getline('.')) 729 edit Xotherbuf 730 buffer Xviewbuf 731 call assert_equal([0, 200, 3, 0], getpos('.')) 732 call assert_equal('200', getline('.')) 733 734 bwipe! Xotherbuf 735 bwipe! Xviewbuf 736 set startofline& 737 endfunc 738 739 func Test_bdelete_skip_closing_bufs() 740 set hidden 741 let s:fired = 0 742 743 edit foo 744 edit bar 745 let s:next_new_bufnr = bufnr('$') + 1 746 augroup SkipClosing 747 autocmd! 748 " Only window and other buffer is closing. 749 " No choice but to switch to a new, empty buffer. 750 autocmd BufDelete * ++once let s:fired += 1 751 \| call assert_equal(1, winnr('$')) 752 \| call assert_equal('bar', bufname()) 753 \| bdelete 754 \| call assert_equal('', bufname()) 755 \| call assert_equal(s:next_new_bufnr, bufnr()) 756 augroup END 757 bdelete foo 758 call assert_equal(1, s:fired) 759 unlet! s:next_new_bufnr 760 %bw! 761 762 edit baz 763 edit bar 764 edit fleb 765 edit foo 766 augroup SkipClosing 767 autocmd! 768 " Only window, au_new_curbuf is NOT closing; should end up there. 769 autocmd BufDelete * ++once let s:fired += 1 770 \| call assert_equal(1, winnr('$')) 771 \| call assert_equal('foo', bufname()) 772 \| bwipeout 773 \| call assert_equal('bar', bufname()) 774 augroup END 775 buffer baz 776 buffer foo 777 augroup SkipClosing 778 autocmd BufLeave * ++once ++nested bdelete baz 779 augroup END 780 edit bar 781 call assert_equal(2, s:fired) 782 %bw! 783 784 edit baz 785 edit bar 786 edit fleb 787 edit foo 788 augroup SkipClosing 789 autocmd! 790 " Like above, but au_new_curbuf IS closing. 791 " Should use the most recent jumplist buffer instead. 792 autocmd BufDelete * ++once let s:fired += 1 793 \| call assert_equal(1, winnr('$')) 794 \| call assert_equal('foo', bufname()) 795 \| bwipeout 796 \| call assert_equal('baz', bufname()) 797 augroup END 798 buffer baz 799 buffer foo 800 augroup SkipClosing 801 autocmd BufLeave * ++once ++nested bdelete bar 802 augroup END 803 edit bar 804 call assert_equal(3, s:fired) 805 %bw! 806 807 edit foo 808 edit floob 809 edit baz 810 edit bar 811 augroup SkipClosing 812 autocmd! 813 " Only window, most recent buffer in jumplist is closing. 814 " Should switch to the next most-recent buffer in the jumplist instead. 815 autocmd BufDelete * ++once let s:fired += 1 816 \| call assert_equal(1, winnr('$')) 817 \| call assert_equal('bar', bufname()) 818 \| bdelete 819 \| call assert_equal('floob', bufname()) 820 augroup END 821 buffer baz 822 buffer floob 823 buffer foo 824 buffer bar 825 bdelete foo 826 call assert_equal(4, s:fired) 827 %bw! 828 829 edit foo 830 edit baz 831 edit bar 832 edit floob 833 edit bazinga 834 augroup SkipClosing 835 autocmd! 836 " Only window, most recent jumplist buffer is gone, next most-recent is 837 " closing. Should switch to the 3rd most-recent jumplist buffer. 838 autocmd BufDelete * ++once let s:fired += 1 839 \| call assert_equal(1, winnr('$')) 840 \| call assert_equal('bar', bufname()) 841 \| bwipeout 842 \| call assert_equal('baz', bufname()) 843 augroup END 844 buffer bazinga 845 buffer baz 846 buffer floob 847 buffer foo 848 buffer bar 849 noautocmd bdelete foo 850 bdelete floob 851 call assert_equal(5, s:fired) 852 %bw! 853 854 edit foo 855 edit baz 856 edit floob 857 edit bazinga 858 edit bar 859 augroup SkipClosing 860 autocmd! 861 " Like above, but jumplist cleared, no next buffer in the buffer list and 862 " previous buffer is closing. Should switch to the buffer before previous. 863 autocmd BufDelete * ++once let s:fired += 1 864 \| call assert_equal(1, winnr('$')) 865 \| call assert_equal('bar', bufname()) 866 \| bunload 867 \| call assert_equal('floob', bufname()) 868 augroup END 869 buffer bazinga 870 buffer baz 871 buffer floob 872 buffer foo 873 buffer bar 874 noautocmd bdelete foo 875 clearjumps 876 bdelete bazinga 877 call assert_equal(6, s:fired) 878 879 unlet! s:fired 880 autocmd! SkipClosing 881 set hidden& 882 %bw! 883 endfunc 884 885 func Test_split_window_in_BufLeave_from_tab_sbuffer() 886 tabnew Xa 887 setlocal bufhidden=wipe 888 let t0 = tabpagenr() 889 let b0 = bufnr() 890 let b1 = bufadd('Xb') 891 autocmd BufLeave Xa ++once split 892 exe 'tab sbuffer' b1 893 call assert_equal(t0 + 1, tabpagenr()) 894 call assert_equal([b1, b0], tabpagebuflist()) 895 call assert_equal([b0], tabpagebuflist(t0)) 896 tabclose 897 call assert_equal(t0, tabpagenr()) 898 call assert_equal([b0], tabpagebuflist()) 899 900 bwipe! Xa 901 bwipe! Xb 902 endfunc 903 904 func Test_split_window_in_BufLeave_from_switching_buffer() 905 tabnew Xa 906 setlocal bufhidden=wipe 907 split 908 let b0 = bufnr() 909 let b1 = bufadd('Xb') 910 autocmd BufLeave Xa ++once split 911 exe 'buffer' b1 912 call assert_equal([b1, b0, b0], tabpagebuflist()) 913 914 bwipe! Xa 915 bwipe! Xb 916 endfunc 917 918 " vim: shiftwidth=2 sts=2 expandtab