summaryrefslogtreecommitdiff
path: root/mnv/src/testdir/test_buffer.mnv
diff options
context:
space:
mode:
authorMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-04 12:41:27 +0300
committerMehmet Samet Duman <yongdohyun@projecttick.org>2026-04-04 12:41:27 +0300
commit4f2d36194b4f299aa7509d815c07121039ea833b (patch)
treef3ded014bad3a4c76ff6a22b8726ebaab68c3d13 /mnv/src/testdir/test_buffer.mnv
parent5b578e70c314723a3cde5c9bfc2be0bf1dadc93b (diff)
downloadProject-Tick-4f2d36194b4f299aa7509d815c07121039ea833b.tar.gz
Project-Tick-4f2d36194b4f299aa7509d815c07121039ea833b.zip
NOISSUE change uvim folder name to mnv
Signed-off-by: Mehmet Samet Duman <yongdohyun@projecttick.org>
Diffstat (limited to 'mnv/src/testdir/test_buffer.mnv')
-rw-r--r--mnv/src/testdir/test_buffer.mnv916
1 files changed, 916 insertions, 0 deletions
diff --git a/mnv/src/testdir/test_buffer.mnv b/mnv/src/testdir/test_buffer.mnv
new file mode 100644
index 0000000000..fd270f0016
--- /dev/null
+++ b/mnv/src/testdir/test_buffer.mnv
@@ -0,0 +1,916 @@
+" Tests for MNV buffer
+
+" Test for the :bunload command with an offset
+func Test_bunload_with_offset()
+ %bwipe!
+ call writefile(['B1'], 'Xb1', 'D')
+ call writefile(['B2'], 'Xb2', 'D')
+ call writefile(['B3'], 'Xb3', 'D')
+ call writefile(['B4'], 'Xb4', 'D')
+
+ " Load four buffers. Unload the second and third buffers and then
+ " execute .+3bunload to unload the last buffer.
+ edit Xb1
+ new Xb2
+ new Xb3
+ new Xb4
+
+ bunload Xb2
+ bunload Xb3
+ exe bufwinnr('Xb1') . 'wincmd w'
+ .+3bunload
+ call assert_equal(0, getbufinfo('Xb4')[0].loaded)
+ call assert_equal('Xb1',
+ \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t'))
+
+ " Load four buffers. Unload the third and fourth buffers. Execute .+3bunload
+ " and check whether the second buffer is unloaded.
+ ball
+ bunload Xb3
+ bunload Xb4
+ exe bufwinnr('Xb1') . 'wincmd w'
+ .+3bunload
+ call assert_equal(0, getbufinfo('Xb2')[0].loaded)
+ call assert_equal('Xb1',
+ \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t'))
+
+ " Load four buffers. Unload the second and third buffers and from the last
+ " buffer execute .-3bunload to unload the first buffer.
+ ball
+ bunload Xb2
+ bunload Xb3
+ exe bufwinnr('Xb4') . 'wincmd w'
+ .-3bunload
+ call assert_equal(0, getbufinfo('Xb1')[0].loaded)
+ call assert_equal('Xb4',
+ \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t'))
+
+ " Load four buffers. Unload the first and second buffers. Execute .-3bunload
+ " from the last buffer and check whether the third buffer is unloaded.
+ ball
+ bunload Xb1
+ bunload Xb2
+ exe bufwinnr('Xb4') . 'wincmd w'
+ .-3bunload
+ call assert_equal(0, getbufinfo('Xb3')[0].loaded)
+ call assert_equal('Xb4',
+ \ fnamemodify(getbufinfo({'bufloaded' : 1})[0].name, ':t'))
+
+ %bwipe!
+
+ call assert_fails('1,4bunload', 'E16:')
+ call assert_fails(',100bunload', 'E16:')
+
+ call assert_fails('$bunload', 'E90:')
+endfunc
+
+" Test for :buffer, :bnext, :bprevious, :brewind, :blast and :bmodified
+" commands
+func Test_buflist_browse()
+ %bwipe!
+ call assert_fails('buffer 1000', 'E86:')
+
+ call writefile(['foo1', 'foo2', 'foo3', 'foo4'], 'Xbrowse1', 'D')
+ call writefile(['bar1', 'bar2', 'bar3', 'bar4'], 'Xbrowse2', 'D')
+ call writefile(['baz1', 'baz2', 'baz3', 'baz4'], 'Xbrowse3', 'D')
+ edit Xbrowse1
+ let b1 = bufnr()
+ edit Xbrowse2
+ let b2 = bufnr()
+ edit +/baz4 Xbrowse3
+ let b3 = bufnr()
+
+ call assert_fails('buffer ' .. b1 .. ' abc', 'E488:')
+ call assert_equal(b3, bufnr())
+ call assert_equal(4, line('.'))
+ exe 'buffer +/bar2 ' .. b2
+ call assert_equal(b2, bufnr())
+ call assert_equal(2, line('.'))
+ exe 'buffer +/bar1'
+ call assert_equal(b2, bufnr())
+ call assert_equal(1, line('.'))
+
+ brewind +
+ call assert_equal(b1, bufnr())
+ call assert_equal(4, line('.'))
+
+ blast +/baz2
+ call assert_equal(b3, bufnr())
+ call assert_equal(2, line('.'))
+
+ bprevious +/bar4
+ call assert_equal(b2, bufnr())
+ call assert_equal(4, line('.'))
+
+ bnext +/baz3
+ call assert_equal(b3, bufnr())
+ call assert_equal(3, line('.'))
+
+ call assert_fails('bmodified', 'E84:')
+ call setbufvar(b2, '&modified', 1)
+ exe 'bmodified +/bar3'
+ call assert_equal(b2, bufnr())
+ call assert_equal(3, line('.'))
+
+ " With no listed buffers in the list, :bnext and :bprev should fail
+ %bwipe!
+ set nobuflisted
+ call assert_fails('bnext', 'E85:')
+ call assert_fails('bprev', 'E85:')
+ set buflisted
+
+ call assert_fails('sandbox bnext', 'E48:')
+
+ %bwipe!
+endfunc
+
+" Test for :bnext and :bprev when called from help and non-help buffers.
+func Test_bnext_bprev_help()
+ %bwipe!
+
+ e XHelp1 | set bt=help
+ let b1 = bufnr()
+ e Xbuf1
+ let b2 = bufnr()
+
+ " There's only one buffer of each type.
+ b XHelp1
+ bnext | call assert_equal(b1, bufnr())
+ bprev | call assert_equal(b1, bufnr())
+ b Xbuf1
+ bnext | call assert_equal(b2, bufnr())
+ bprev | call assert_equal(b2, bufnr())
+
+ " Add one more buffer of each type.
+ e XHelp2 | set bt=help
+ let b3 = bufnr()
+ e Xbuf2
+ let b4 = bufnr()
+
+ " Help buffer jumps to help buffer.
+ b XHelp1
+ bnext | call assert_equal(b3, bufnr())
+ bnext | call assert_equal(b1, bufnr())
+ bprev | call assert_equal(b3, bufnr())
+ bprev | call assert_equal(b1, bufnr())
+
+ " Regular buffer jumps to regular buffer.
+ b Xbuf1
+ bnext | call assert_equal(b4, bufnr())
+ bnext | call assert_equal(b2, bufnr())
+ bprev | call assert_equal(b4, bufnr())
+ bprev | call assert_equal(b2, bufnr())
+
+ " :brewind and :blast are not affected by the buffer type.
+ b Xbuf2
+ brewind | call assert_equal(b1, bufnr())
+ b XHelp1
+ blast | call assert_equal(b4, bufnr())
+
+ " Cycling through help buffers works even if they aren't listed.
+ b XHelp1
+ setlocal nobuflisted
+ bnext | call assert_equal(b3, bufnr())
+ bnext | call assert_equal(b1, bufnr())
+ bprev | call assert_equal(b3, bufnr())
+ setlocal nobuflisted
+ bprev | call assert_equal(b1, bufnr())
+ bprev | call assert_equal(b3, bufnr())
+ bnext | call assert_equal(b1, bufnr())
+
+ %bwipe!
+endfunc
+
+" Test for :bdelete
+func Test_bdelete_cmd()
+ %bwipe!
+ call assert_fails('bdelete 5', 'E516:')
+ call assert_fails('1,1bdelete 1 2', 'E488:')
+ call assert_fails('bdelete \)', 'E55:')
+
+ " Deleting an unlisted and unloaded buffer
+ edit Xbdelfile1
+ let bnr = bufnr()
+ set nobuflisted
+ enew
+ call assert_fails('bdelete ' .. bnr, 'E516:')
+
+ " Deleting more than one buffer
+ new Xbuf1
+ new Xbuf2
+ exe 'bdel ' .. bufnr('Xbuf2') .. ' ' .. bufnr('Xbuf1')
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('Xbuf1')[0].loaded)
+ call assert_equal(0, getbufinfo('Xbuf2')[0].loaded)
+
+ " Deleting more than one buffer and an invalid buffer
+ new Xbuf1
+ new Xbuf2
+ let cmd = "exe 'bdel ' .. bufnr('Xbuf2') .. ' xxx ' .. bufnr('Xbuf1')"
+ call assert_fails(cmd, 'E94:')
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, getbufinfo('Xbuf1')[0].loaded)
+ call assert_equal(0, getbufinfo('Xbuf2')[0].loaded)
+
+ %bwipe!
+endfunc
+
+func Test_buffer_error()
+ new foo1
+ new foo2
+
+ call assert_fails('buffer foo', 'E93:')
+ call assert_fails('buffer bar', 'E94:')
+ call assert_fails('buffer 0', 'E939:')
+
+ %bwipe
+endfunc
+
+func Test_bwipe_during_save()
+ set charconvert=execute('%bw!')
+ call assert_fails('write ++enc=lmao boom', 'E937:')
+
+ set charconvert&
+ %bwipe
+endfunc
+
+" Test for the status messages displayed when unloading, deleting or wiping
+" out buffers
+func Test_buffer_statusmsg()
+ CheckEnglish
+ set report=1
+ new Xbuf1
+ new Xbuf2
+ let bnr = bufnr()
+ exe "normal 2\<C-G>"
+ call assert_match('buf ' .. bnr .. ':', v:statusmsg)
+ bunload Xbuf1 Xbuf2
+ call assert_equal('2 buffers unloaded', v:statusmsg)
+ bdel Xbuf1 Xbuf2
+ call assert_equal('2 buffers deleted', v:statusmsg)
+ bwipe Xbuf1 Xbuf2
+ call assert_equal('2 buffers wiped out', v:statusmsg)
+ set report&
+endfunc
+
+" Test for quitting the 'swapfile exists' dialog with the split buffer
+" command.
+func Test_buffer_sbuf_cleanup()
+ call writefile([], 'XsplitCleanup', 'D')
+ " first open the file in a buffer
+ new XsplitCleanup
+ let bnr = bufnr()
+ close
+ " create the swap file
+ call writefile([], '.XsplitCleanup.swp', 'D')
+ " Remove the catch-all that runtest.mnv adds
+ au! SwapExists
+ augroup BufTest
+ au!
+ autocmd SwapExists XsplitCleanup let v:swapchoice='q'
+ augroup END
+ exe 'sbuf ' . bnr
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('XsplitCleanup')[0].loaded)
+
+ " test for :sball
+ sball
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('XsplitCleanup')[0].loaded)
+
+ %bw!
+ set shortmess+=F
+ let v:statusmsg = ''
+ edit XsplitCleanup
+ call assert_equal('', v:statusmsg)
+ call assert_equal(1, winnr('$'))
+ call assert_equal(0, getbufinfo('XsplitCleanup')[0].loaded)
+ set shortmess&
+
+ augroup BufTest
+ au!
+ augroup END
+ augroup! BufTest
+endfunc
+
+" Test for deleting a modified buffer with :confirm
+func Test_bdel_with_confirm()
+ CheckUnix
+ CheckNotGui
+ CheckFeature dialog_con
+ new
+ call setline(1, 'test')
+ call assert_fails('bdel', 'E89:')
+ call feedkeys('c', 'L')
+ confirm bdel
+ call assert_equal(2, winnr('$'))
+ call assert_equal(1, &modified)
+ call feedkeys('n', 'L')
+ confirm bdel
+ call assert_equal(1, winnr('$'))
+endfunc
+
+" Test for editing another buffer from a modified buffer with :confirm
+func Test_goto_buf_with_confirm()
+ CheckUnix
+ CheckNotGui
+ CheckFeature dialog_con
+ " When dialog_con_gui is defined, MNV is compiled with GUI support
+ " and FEAT_BROWSE will be defined, which causes :confirm :b to
+ " call do_browse(), which will try to use a GUI file browser,
+ " which aborts if a GUI is not available.
+ CheckNotFeature dialog_con_gui
+ new XgotoConf
+ enew
+ call setline(1, 'test')
+ call assert_fails('b XgotoConf', 'E37:')
+ call feedkeys('c', 'L')
+ call assert_fails('confirm b XgotoConf', 'E37:')
+ call assert_true(&modified)
+ call assert_true(empty(bufname('%')))
+ call feedkeys('y', 'L')
+ confirm b XgotoConf
+ call assert_equal('XgotoConf', bufname('%'))
+ call assert_equal(['test'], readfile('Untitled'))
+ e Untitled
+ call setline(2, 'test2')
+ call feedkeys('n', 'L')
+ confirm b XgotoConf
+ call assert_equal('XgotoConf', bufname('%'))
+ call assert_equal(['test'], readfile('Untitled'))
+ call delete('Untitled')
+ close!
+endfunc
+
+" Test for splitting buffer with 'switchbuf'
+func Test_buffer_switchbuf()
+ new Xswitchbuf
+ wincmd w
+ set switchbuf=useopen
+ sbuf Xswitchbuf
+ call assert_equal(1, winnr())
+ call assert_equal(2, winnr('$'))
+ set switchbuf=usetab
+ tabnew
+ sbuf Xswitchbuf
+ call assert_equal(1, tabpagenr())
+ call assert_equal(2, tabpagenr('$'))
+ set switchbuf&
+ %bw
+endfunc
+
+" Test for BufAdd autocommand wiping out the buffer
+func Test_bufadd_autocmd_bwipe()
+ %bw!
+ augroup BufAdd_Wipe
+ au!
+ autocmd BufAdd Xbwipe %bw!
+ augroup END
+ edit Xbwipe
+ call assert_equal('', @%)
+ call assert_equal(0, bufexists('Xbwipe'))
+ augroup BufAdd_Wipe
+ au!
+ augroup END
+ augroup! BufAdd_Wipe
+endfunc
+
+" Test for trying to load a buffer with text locked
+" <C-\>e in the command line is used to lock the text
+func Test_load_buf_with_text_locked()
+ new Xlockfile1
+ edit Xlockfile2
+ let cmd = ":\<C-\>eexecute(\"normal \<C-O>\")\<CR>\<C-C>"
+ call assert_fails("call feedkeys(cmd, 'xt')", 'E565:')
+ %bw!
+endfunc
+
+" Test for using CTRL-^ to edit the alternative file keeping the cursor
+" position with 'nostartofline'. Also test using the 'buf' command.
+func Test_buffer_edit_altfile()
+ call writefile(repeat(['one two'], 50), 'Xaltfile1', 'D')
+ call writefile(repeat(['five six'], 50), 'Xaltfile2', 'D')
+ set nosol
+ edit Xaltfile1
+ call cursor(25, 5)
+ edit Xaltfile2
+ call cursor(30, 4)
+ exe "normal \<C-^>"
+ call assert_equal([0, 25, 5, 0], getpos('.'))
+ exe "normal \<C-^>"
+ call assert_equal([0, 30, 4, 0], getpos('.'))
+ buf Xaltfile1
+ call assert_equal([0, 25, 5, 0], getpos('.'))
+ buf Xaltfile2
+ call assert_equal([0, 30, 4, 0], getpos('.'))
+ set sol&
+endfunc
+
+" Test for running the :sball command with a maximum window count and a
+" modified buffer
+func Test_sball_with_count()
+ %bw!
+ edit Xcountfile1
+ call setline(1, ['abc'])
+ new Xcountfile2
+ new Xcountfile3
+ new Xcountfile4
+ 2sball
+ call assert_equal(bufnr('Xcountfile4'), winbufnr(1))
+ call assert_equal(bufnr('Xcountfile1'), winbufnr(2))
+ call assert_equal(0, getbufinfo('Xcountfile2')[0].loaded)
+ call assert_equal(0, getbufinfo('Xcountfile3')[0].loaded)
+ %bw!
+endfunc
+
+func Test_badd_options()
+ new SomeNewBuffer
+ setlocal numberwidth=3
+ wincmd p
+ badd +1 SomeNewBuffer
+ new SomeNewBuffer
+ call assert_equal(3, &numberwidth)
+ close
+ close
+ bwipe! SomeNewBuffer
+
+ badd +3 XbaddFile
+ call writefile(range(6), 'XbaddFile', 'D')
+ buf XbaddFile
+ call assert_equal([0, 3, 1, 0], getpos('.'))
+
+ bwipe! XbaddFile
+endfunc
+
+func Test_balt()
+ new SomeNewBuffer
+ balt +3 OtherBuffer
+ e #
+ call assert_equal('OtherBuffer', bufname())
+endfunc
+
+" Test for buffer match URL(scheme) check
+" scheme is alpha and inner hyphen only.
+func Test_buffer_scheme()
+ CheckMSWindows
+
+ set noswapfile
+ set noshellslash
+ %bwipe!
+ let bufnames = [
+ \ #{id: 'ssb0', name: 'test://xyz/foo/ssb0' , match: 1},
+ \ #{id: 'ssb1', name: 'test+abc://xyz/foo/ssb1', match: 0},
+ \ #{id: 'ssb2', name: 'test_abc://xyz/foo/ssb2', match: 0},
+ \ #{id: 'ssb3', name: 'test-abc://xyz/foo/ssb3', match: 1},
+ \ #{id: 'ssb4', name: '-test://xyz/foo/ssb4' , match: 0},
+ \ #{id: 'ssb5', name: 'test-://xyz/foo/ssb5' , match: 0},
+ \]
+ for buf in bufnames
+ new `=buf.name`
+ if buf.match
+ call assert_equal(buf.name, getbufinfo(buf.id)[0].name)
+ else
+ " slashes will have become backslashes
+ call assert_notequal(buf.name, getbufinfo(buf.id)[0].name)
+ endif
+ bwipe
+ endfor
+
+ set shellslash&
+ set swapfile&
+endfunc
+
+" this was using a NULL pointer after failing to use the pattern
+func Test_buf_pattern_invalid()
+ vsplit 0000000
+ silent! buf [0--]\&\zs*\zs*e
+ bwipe!
+
+ vsplit 00000000000000000000000000
+ silent! buf [0--]\&\zs*\zs*e
+ bwipe!
+
+ " similar case with different code path
+ split 0
+ edit ΓΏ
+ silent! buf [0--]\&\zs*\zs*0
+ bwipe!
+endfunc
+
+" Test for the 'maxmem' and 'maxmemtot' options
+func Test_buffer_maxmem()
+ " use 1KB per buffer and 2KB for all the buffers
+ set maxmem=1 maxmemtot=2
+ new
+ let v:errmsg = ''
+ " try opening some files
+ edit test_arglist.mnv
+ call assert_equal('test_arglist.mnv', bufname())
+ edit test_eval_stuff.mnv
+ call assert_equal('test_eval_stuff.mnv', bufname())
+ b test_arglist.mnv
+ call assert_equal('test_arglist.mnv', bufname())
+ b test_eval_stuff.mnv
+ call assert_equal('test_eval_stuff.mnv', bufname())
+ close
+ call assert_equal('', v:errmsg)
+ set maxmem& maxmemtot&
+endfunc
+
+" Test for buffer allocation failure
+func Test_buflist_alloc_failure()
+ %bw!
+
+ edit XallocFail1
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('edit XallocFail2', 'E342:')
+
+ " test for bufadd()
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('call bufadd("Xbuffer")', 'E342:')
+
+ " test for setting the arglist
+ edit XallocFail2
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('next XallocFail3', 'E342:')
+
+ " test for setting the alternate buffer name when writing a file
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('write Xother', 'E342:')
+ call delete('Xother')
+
+ " test for creating a buffer using bufnr()
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails("call bufnr('Xnewbuf', v:true)", 'E342:')
+
+ " test for renaming buffer using :file
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('file Xnewfile', 'E342:')
+
+ " test for creating a buffer for a popup window
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('call popup_create("mypop", {})', 'E342:')
+
+ if has('terminal')
+ " test for creating a buffer for a terminal window
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('call term_start(&shell)', 'E342:')
+ %bw!
+ endif
+
+ " test for loading a new buffer after wiping out all the buffers
+ edit XallocFail4
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('%bw!', 'E342:')
+
+ " test for :checktime loading the buffer
+ call writefile(['one'], 'XallocFail5', 'D')
+ if has('unix')
+ edit XallocFail5
+ " sleep for some time to make sure the timestamp is different
+ sleep 200m
+ call writefile(['two'], 'XallocFail5')
+ set autoread
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('checktime', 'E342:')
+ set autoread&
+ bw!
+ endif
+
+ " test for :mnvgrep loading a dummy buffer
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('mnvgrep two XallocFail5', 'E342:')
+
+ " test for quickfix command loading a buffer
+ call test_alloc_fail(GetAllocId('newbuf_bvars'), 0, 0)
+ call assert_fails('cexpr "XallocFail6:10:Line10"', 'E342:')
+endfunc
+
+func Test_closed_buffer_still_in_window()
+ %bw!
+
+ let s:fired = 0
+ let s:w = win_getid()
+ new
+ let s:b = bufnr()
+ setl bufhidden=wipe
+ augroup ViewClosedBuffer
+ autocmd!
+ autocmd BufUnload * ++once let s:fired += 1 | call assert_fails(
+ \ 'call win_execute(s:w, "' .. s:b .. 'buffer")', 'E1546:')
+ augroup END
+ quit!
+ " Previously resulted in s:b being curbuf while unloaded (no memfile).
+ call assert_equal(1, s:fired)
+ call assert_equal(1, bufloaded(bufnr()))
+ call assert_equal(0, bufexists(s:b))
+ %bw!
+
+ new flobby
+ let s:w = win_getid()
+ let s:b = bufnr()
+ setl bufhidden=wipe
+ augroup ViewClosedBuffer
+ autocmd!
+ autocmd BufUnload * ++once let s:fired += 1
+ \| wincmd p
+ \| call assert_notequal(s:w, win_getid())
+ \| call assert_notequal(s:b, bufnr())
+ \| execute s:b 'sbuffer'
+ \| call assert_equal(s:w, win_getid())
+ \| call assert_equal(s:b, bufnr())
+ augroup END
+ " Not a problem if 'switchbuf' switches to an existing window instead.
+ set switchbuf=useopen
+ quit!
+ call assert_equal(2, s:fired)
+ call assert_equal(0, bufexists(s:b))
+ set switchbuf&
+ %bw!
+
+ edit floob
+ let s:b = bufnr()
+ enew
+ augroup ViewClosedBuffer
+ autocmd!
+ autocmd BufWipeout * ++once let s:fired += 1
+ \| call assert_fails(s:b .. 'sbuffer | wincmd p', 'E1546:')
+ \| call assert_equal(1, winnr('$')) " :sbuffer shouldn't have split.
+ augroup END
+ " Used to be a heap UAF.
+ execute s:b 'bwipeout!'
+ call assert_equal(3, s:fired)
+ call assert_equal(0, bufexists(s:b))
+ %bw!
+
+ edit flarb
+ let s:b = bufnr()
+ enew
+ let b2 = bufnr()
+ augroup ViewClosedBuffer
+ autocmd!
+ autocmd BufWipeout * ++once let s:fired += 1
+ \| call assert_fails(s:b .. 'sbuffer', 'E1159:')
+ augroup END
+ " :sbuffer still should fail if curbuf is closing, even if it's not the target
+ " buffer (as switching buffers can fail after the split)
+ bwipeout!
+ call assert_equal(4, s:fired)
+ call assert_equal(0, bufexists(b2))
+ %bw!
+
+ let s:w = win_getid()
+ split
+ new
+ let s:b = bufnr()
+ augroup ViewClosedBuffer
+ autocmd!
+ autocmd BufWipeout * ++once let s:fired += 1 | call win_gotoid(s:w)
+ \| call assert_fails(s:b .. 'buffer', 'E1546:') | wincmd p
+ augroup END
+ bw! " Close only this buffer first; used to be a heap UAF.
+ call assert_equal(5, s:fired)
+
+ unlet! s:w s:b s:fired
+ autocmd! ViewClosedBuffer
+ %bw!
+endfunc
+
+" Cursor position should be restored when switching to a buffer previously
+" viewed in a window, regardless of whether it's visible in another one.
+func Test_switch_to_previously_viewed_buffer()
+ set nostartofline
+ new Xviewbuf
+ call setline(1, range(1, 200))
+ let oldwin = win_getid()
+ vsplit
+
+ call cursor(100, 3)
+ call assert_equal('100', getline('.'))
+ edit Xotherbuf
+ buffer Xviewbuf
+ call assert_equal([0, 100, 3, 0], getpos('.'))
+ call assert_equal('100', getline('.'))
+
+ edit Xotherbuf
+ wincmd p
+ normal! gg10dd
+ wincmd p
+ buffer Xviewbuf
+ call assert_equal([0, 90, 3, 0], getpos('.'))
+ call assert_equal('100', getline('.'))
+
+ edit Xotherbuf
+ wincmd p
+ normal! ggP
+ wincmd p
+ buffer Xviewbuf
+ call assert_equal([0, 100, 3, 0], getpos('.'))
+ call assert_equal('100', getline('.'))
+
+ edit Xotherbuf
+ wincmd p
+ normal! 96gg10ddgg
+ wincmd p
+ buffer Xviewbuf
+ " The original cursor line was deleted, so cursor is restored to the start
+ " of the line before the deleted range.
+ call assert_equal([0, 95, 1, 0], getpos('.'))
+ call assert_equal('95', getline('.'))
+
+ normal! u
+ exe win_id2win(oldwin) .. 'close'
+ setlocal bufhidden=hide
+
+ call cursor(200, 3)
+ call assert_equal('200', getline('.'))
+ edit Xotherbuf
+ buffer Xviewbuf
+ call assert_equal([0, 200, 3, 0], getpos('.'))
+ call assert_equal('200', getline('.'))
+
+ bwipe! Xotherbuf
+ bwipe! Xviewbuf
+ set startofline&
+endfunc
+
+func Test_bdelete_skip_closing_bufs()
+ set hidden
+ let s:fired = 0
+
+ edit foo
+ edit bar
+ let s:next_new_bufnr = bufnr('$') + 1
+ augroup SkipClosing
+ autocmd!
+ " Only window and other buffer is closing.
+ " No choice but to switch to a new, empty buffer.
+ autocmd BufDelete * ++once let s:fired += 1
+ \| call assert_equal(1, winnr('$'))
+ \| call assert_equal('bar', bufname())
+ \| bdelete
+ \| call assert_equal('', bufname())
+ \| call assert_equal(s:next_new_bufnr, bufnr())
+ augroup END
+ bdelete foo
+ call assert_equal(1, s:fired)
+ unlet! s:next_new_bufnr
+ %bw!
+
+ edit baz
+ edit bar
+ edit fleb
+ edit foo
+ augroup SkipClosing
+ autocmd!
+ " Only window, au_new_curbuf is NOT closing; should end up there.
+ autocmd BufDelete * ++once let s:fired += 1
+ \| call assert_equal(1, winnr('$'))
+ \| call assert_equal('foo', bufname())
+ \| bwipeout
+ \| call assert_equal('bar', bufname())
+ augroup END
+ buffer baz
+ buffer foo
+ augroup SkipClosing
+ autocmd BufLeave * ++once ++nested bdelete baz
+ augroup END
+ edit bar
+ call assert_equal(2, s:fired)
+ %bw!
+
+ edit baz
+ edit bar
+ edit fleb
+ edit foo
+ augroup SkipClosing
+ autocmd!
+ " Like above, but au_new_curbuf IS closing.
+ " Should use the most recent jumplist buffer instead.
+ autocmd BufDelete * ++once let s:fired += 1
+ \| call assert_equal(1, winnr('$'))
+ \| call assert_equal('foo', bufname())
+ \| bwipeout
+ \| call assert_equal('baz', bufname())
+ augroup END
+ buffer baz
+ buffer foo
+ augroup SkipClosing
+ autocmd BufLeave * ++once ++nested bdelete bar
+ augroup END
+ edit bar
+ call assert_equal(3, s:fired)
+ %bw!
+
+ edit foo
+ edit floob
+ edit baz
+ edit bar
+ augroup SkipClosing
+ autocmd!
+ " Only window, most recent buffer in jumplist is closing.
+ " Should switch to the next most-recent buffer in the jumplist instead.
+ autocmd BufDelete * ++once let s:fired += 1
+ \| call assert_equal(1, winnr('$'))
+ \| call assert_equal('bar', bufname())
+ \| bdelete
+ \| call assert_equal('floob', bufname())
+ augroup END
+ buffer baz
+ buffer floob
+ buffer foo
+ buffer bar
+ bdelete foo
+ call assert_equal(4, s:fired)
+ %bw!
+
+ edit foo
+ edit baz
+ edit bar
+ edit floob
+ edit bazinga
+ augroup SkipClosing
+ autocmd!
+ " Only window, most recent jumplist buffer is gone, next most-recent is
+ " closing. Should switch to the 3rd most-recent jumplist buffer.
+ autocmd BufDelete * ++once let s:fired += 1
+ \| call assert_equal(1, winnr('$'))
+ \| call assert_equal('bar', bufname())
+ \| bwipeout
+ \| call assert_equal('baz', bufname())
+ augroup END
+ buffer bazinga
+ buffer baz
+ buffer floob
+ buffer foo
+ buffer bar
+ noautocmd bdelete foo
+ bdelete floob
+ call assert_equal(5, s:fired)
+ %bw!
+
+ edit foo
+ edit baz
+ edit floob
+ edit bazinga
+ edit bar
+ augroup SkipClosing
+ autocmd!
+ " Like above, but jumplist cleared, no next buffer in the buffer list and
+ " previous buffer is closing. Should switch to the buffer before previous.
+ autocmd BufDelete * ++once let s:fired += 1
+ \| call assert_equal(1, winnr('$'))
+ \| call assert_equal('bar', bufname())
+ \| bunload
+ \| call assert_equal('floob', bufname())
+ augroup END
+ buffer bazinga
+ buffer baz
+ buffer floob
+ buffer foo
+ buffer bar
+ noautocmd bdelete foo
+ clearjumps
+ bdelete bazinga
+ call assert_equal(6, s:fired)
+
+ unlet! s:fired
+ autocmd! SkipClosing
+ set hidden&
+ %bw!
+endfunc
+
+func Test_split_window_in_BufLeave_from_tab_sbuffer()
+ tabnew Xa
+ setlocal bufhidden=wipe
+ let t0 = tabpagenr()
+ let b0 = bufnr()
+ let b1 = bufadd('Xb')
+ autocmd BufLeave Xa ++once split
+ exe 'tab sbuffer' b1
+ call assert_equal(t0 + 1, tabpagenr())
+ call assert_equal([b1, b0], tabpagebuflist())
+ call assert_equal([b0], tabpagebuflist(t0))
+ tabclose
+ call assert_equal(t0, tabpagenr())
+ call assert_equal([b0], tabpagebuflist())
+
+ bwipe! Xa
+ bwipe! Xb
+endfunc
+
+func Test_split_window_in_BufLeave_from_switching_buffer()
+ tabnew Xa
+ setlocal bufhidden=wipe
+ split
+ let b0 = bufnr()
+ let b1 = bufadd('Xb')
+ autocmd BufLeave Xa ++once split
+ exe 'buffer' b1
+ call assert_equal([b1, b0, b0], tabpagebuflist())
+
+ bwipe! Xa
+ bwipe! Xb
+endfunc
+
+" mnv: shiftwidth=2 sts=2 expandtab