neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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