aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorzeertzjq <zeertzjq@outlook.com>2022-11-07 07:58:37 +0800
committerGitHub <noreply@github.com>2022-11-07 07:58:37 +0800
commit9b9f84bc62a01ed76b9f53119781816bd3375267 (patch)
treec1c6e5463d515ddc174ca71554d1203f29983c28 /src
parent3b3611a3d0f1e13e277360d6bacf97a0fb7eb6de (diff)
parent7e1d9c560b09cacb78b2fc8f9428a77d6fca66e1 (diff)
downloadrneovim-9b9f84bc62a01ed76b9f53119781816bd3375267.tar.gz
rneovim-9b9f84bc62a01ed76b9f53119781816bd3375267.tar.bz2
rneovim-9b9f84bc62a01ed76b9f53119781816bd3375267.zip
Merge pull request #20982 from zeertzjq/vim-8.2.2849
vim-patch:8.2.{2849,2856,2873}: buffer writing tests
Diffstat (limited to 'src')
-rw-r--r--src/nvim/ex_cmds.c17
-rw-r--r--src/nvim/testdir/test_buffer.vim20
-rw-r--r--src/nvim/testdir/test_cmdline.vim21
-rw-r--r--src/nvim/testdir/test_functions.vim1
-rw-r--r--src/nvim/testdir/test_startup.vim15
-rw-r--r--src/nvim/testdir/test_writefile.vim219
6 files changed, 290 insertions, 3 deletions
diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c
index 89e6d47950..d3a4b6c282 100644
--- a/src/nvim/ex_cmds.c
+++ b/src/nvim/ex_cmds.c
@@ -1772,6 +1772,17 @@ void ex_write(exarg_T *eap)
}
}
+#ifdef UNIX
+static int check_writable(const char *fname)
+{
+ if (os_nodetype(fname) == NODE_OTHER) {
+ semsg(_("E503: \"%s\" is not a file or writable device"), fname);
+ return FAIL;
+ }
+ return OK;
+}
+#endif
+
/// write current buffer to file 'eap->arg'
/// if 'eap->append' is true, append to the file
///
@@ -1829,7 +1840,11 @@ int do_write(exarg_T *eap)
// Writing to the current file is not allowed in readonly mode
// and a file name is required.
// "nofile" and "nowrite" buffers cannot be written implicitly either.
- if (!other && (bt_dontwrite_msg(curbuf) || check_fname() == FAIL
+ if (!other && (bt_dontwrite_msg(curbuf)
+ || check_fname() == FAIL
+#ifdef UNIX
+ || check_writable(curbuf->b_ffname) == FAIL
+#endif
|| check_readonly(&eap->forceit, curbuf))) {
goto theend;
}
diff --git a/src/nvim/testdir/test_buffer.vim b/src/nvim/testdir/test_buffer.vim
index d8d22ff872..3300278802 100644
--- a/src/nvim/testdir/test_buffer.vim
+++ b/src/nvim/testdir/test_buffer.vim
@@ -434,4 +434,24 @@ func Test_buf_pattern_invalid()
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.vim
+ call assert_equal('test_arglist.vim', bufname())
+ edit test_eval_stuff.vim
+ call assert_equal('test_eval_stuff.vim', bufname())
+ b test_arglist.vim
+ call assert_equal('test_arglist.vim', bufname())
+ b test_eval_stuff.vim
+ call assert_equal('test_eval_stuff.vim', bufname())
+ close
+ call assert_equal('', v:errmsg)
+ " set maxmem& maxmemtot&
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_cmdline.vim b/src/nvim/testdir/test_cmdline.vim
index 7cef3117c2..b0be7ab396 100644
--- a/src/nvim/testdir/test_cmdline.vim
+++ b/src/nvim/testdir/test_cmdline.vim
@@ -1513,6 +1513,7 @@ func Test_cmdline_expand_special()
call assert_fails('e <afile>', 'E495:')
call assert_fails('e <abuf>', 'E496:')
call assert_fails('e <amatch>', 'E497:')
+
call writefile([], 'Xfile.cpp')
call writefile([], 'Xfile.java')
new Xfile.cpp
@@ -2006,6 +2007,26 @@ func Test_recalling_cmdline()
cunmap <Plug>(save-cmdline)
endfunc
+" Test for the 'suffixes' option
+func Test_suffixes_opt()
+ call writefile([], 'Xfile')
+ call writefile([], 'Xfile.c')
+ call writefile([], 'Xfile.o')
+ set suffixes=
+ call feedkeys(":e Xfi*\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e Xfile Xfile.c Xfile.o', @:)
+ set suffixes=.c
+ call feedkeys(":e Xfi*\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e Xfile Xfile.o Xfile.c', @:)
+ set suffixes=,,
+ call feedkeys(":e Xfi*\<C-A>\<C-B>\"\<CR>", 'xt')
+ call assert_equal('"e Xfile.c Xfile.o Xfile', @:)
+ set suffixes&
+ call delete('Xfile')
+ call delete('Xfile.c')
+ call delete('Xfile.o')
+endfunc
+
" Test for using a popup menu for the command line completion matches
" (wildoptions=pum)
func Test_wildmenu_pum()
diff --git a/src/nvim/testdir/test_functions.vim b/src/nvim/testdir/test_functions.vim
index b464f6591d..0f2066b7c1 100644
--- a/src/nvim/testdir/test_functions.vim
+++ b/src/nvim/testdir/test_functions.vim
@@ -2454,6 +2454,7 @@ endfunc
func Test_glob()
call assert_equal('', glob(v:_null_string))
call assert_equal('', globpath(v:_null_string, v:_null_string))
+ call assert_fails("let x = globpath(&rtp, 'syntax/c.vim', [])", 'E745:')
call writefile([], 'Xglob1')
call writefile([], 'XGLOB2')
diff --git a/src/nvim/testdir/test_startup.vim b/src/nvim/testdir/test_startup.vim
index 30bbd355df..f9f7c5b492 100644
--- a/src/nvim/testdir/test_startup.vim
+++ b/src/nvim/testdir/test_startup.vim
@@ -1279,4 +1279,19 @@ func Test_progname()
call delete('Xprogname', 'd')
endfunc
+" Test for doing a write from .vimrc
+func Test_write_in_vimrc()
+ call writefile(['silent! write'], 'Xvimrc')
+ let after =<< trim [CODE]
+ call assert_match('E32: ', v:errmsg)
+ call writefile(v:errors, 'Xtestout')
+ qall
+ [CODE]
+ if RunVim([], after, '-u Xvimrc')
+ call assert_equal([], readfile('Xtestout'))
+ call delete('Xtestout')
+ endif
+ call delete('Xvimrc')
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/nvim/testdir/test_writefile.vim b/src/nvim/testdir/test_writefile.vim
index a7ebe8cde6..81615b5963 100644
--- a/src/nvim/testdir/test_writefile.vim
+++ b/src/nvim/testdir/test_writefile.vim
@@ -57,7 +57,29 @@ func Test_writefile_fails_conversion()
call assert_fails('write ++enc=cp932', 'E513:')
call assert_equal(contents, readfile('Xfile'))
+ " With 'backupcopy' set, if there is a conversion error, the backup file is
+ " still created.
+ set backupcopy=yes writebackup& backup&
+ call delete('Xfile' .. &backupext)
+ call assert_fails('write ++enc=cp932', 'E513:')
+ call assert_equal(contents, readfile('Xfile'))
+ call assert_equal(contents, readfile('Xfile' .. &backupext))
+ set backupcopy&
+ %bw!
+
+ " Conversion error during write
+ new
+ call setline(1, ["\U10000000"])
+ let output = execute('write! ++enc=utf-16 Xfile')
+ call assert_match('CONVERSION ERROR', output)
+ let output = execute('write! ++enc=ucs-2 Xfile')
+ call assert_match('CONVERSION ERROR', output)
+ call delete('Xfilz~')
+ call delete('Xfily~')
+ %bw!
+
call delete('Xfile')
+ call delete('Xfile' .. &backupext)
bwipe!
set backup& writebackup& backupdir&vim backupskip&vim
endfunc
@@ -270,6 +292,16 @@ func Test_write_errors()
let long_fname = repeat('n', 5000)
call assert_fails('exe "w " .. long_fname', 'E75:')
call assert_fails('call writefile([], long_fname)', 'E482:')
+
+ " Test for writing to a block device on Unix-like systems
+ if has('unix') && getfperm('/dev/loop0') != ''
+ \ && getftype('/dev/loop0') == 'bdev' && !IsRoot()
+ new
+ edit /dev/loop0
+ call assert_fails('write', 'E503: ')
+ call assert_fails('write!', 'E503: ')
+ close!
+ endif
endfunc
" Test for writing to a file which is modified after Vim read it
@@ -396,8 +428,21 @@ func Test_write_readonly()
call setline(1, ['line1'])
write!
call assert_equal(['line1'], readfile('Xfile'))
+
+ " Auto-saving a readonly file should fail with 'autowriteall'
+ %bw!
+ e Xfile
+ set noreadonly autowriteall
+ call setline(1, ['aaaa'])
+ call assert_fails('n', 'E505:')
+ set cpo+=W
+ call assert_fails('n', 'E504:')
+ set cpo-=W
+ set autowriteall&
+
set backupskip&
call delete('Xfile')
+ %bw!
endfunc
" Test for 'patchmode'
@@ -413,6 +458,19 @@ func Test_patchmode()
" subsequent writes should not create/modify the .orig file
write
call assert_equal(['one'], readfile('Xfile.orig'))
+
+ " use 'patchmode' with 'nobackup' and 'nowritebackup' to create an empty
+ " original file
+ call delete('Xfile')
+ call delete('Xfile.orig')
+ %bw!
+ set patchmode=.orig nobackup nowritebackup
+ edit Xfile
+ call setline(1, ['xxx'])
+ write
+ call assert_equal(['xxx'], readfile('Xfile'))
+ call assert_equal([], readfile('Xfile.orig'))
+
set patchmode& backup& backupskip& writebackup&
call delete('Xfile')
call delete('Xfile.orig')
@@ -426,7 +484,7 @@ func Test_write_readonly_dir()
" Root can do it too.
CheckNotRoot
- call mkdir('Xdir')
+ call mkdir('Xdir/')
call writefile(['one'], 'Xdir/Xfile1')
call setfperm('Xdir', 'r-xr--r--')
" try to create a new file in the directory
@@ -710,10 +768,167 @@ func Test_read_write_bin()
call assert_equal(0z6E6F656F6C0A, readfile('XNoEolSetEol', 'B'))
call delete('XNoEolSetEol')
- set ff&
+ set ff& fixeol&
bwipe! XNoEolSetEol
endfunc
+" Test for the 'backupcopy' option when writing files
+func Test_backupcopy()
+ CheckUnix
+ set backupskip=
+ " With the default 'backupcopy' setting, saving a symbolic link file
+ " should not break the link.
+ set backupcopy&
+ call writefile(['1111'], 'Xfile1')
+ silent !ln -s Xfile1 Xfile2
+ new Xfile2
+ call setline(1, ['2222'])
+ write
+ close
+ call assert_equal(['2222'], readfile('Xfile1'))
+ call assert_equal('Xfile1', resolve('Xfile2'))
+ call assert_equal('link', getftype('Xfile2'))
+ call delete('Xfile1')
+ call delete('Xfile2')
+
+ " With the 'backupcopy' set to 'breaksymlink', saving a symbolic link file
+ " should break the link.
+ set backupcopy=yes,breaksymlink
+ call writefile(['1111'], 'Xfile1')
+ silent !ln -s Xfile1 Xfile2
+ new Xfile2
+ call setline(1, ['2222'])
+ write
+ close
+ call assert_equal(['1111'], readfile('Xfile1'))
+ call assert_equal(['2222'], readfile('Xfile2'))
+ call assert_equal('Xfile2', resolve('Xfile2'))
+ call assert_equal('file', getftype('Xfile2'))
+ call delete('Xfile1')
+ call delete('Xfile2')
+ set backupcopy&
+
+ " With the default 'backupcopy' setting, saving a hard link file
+ " should not break the link.
+ set backupcopy&
+ call writefile(['1111'], 'Xfile1')
+ silent !ln Xfile1 Xfile2
+ new Xfile2
+ call setline(1, ['2222'])
+ write
+ close
+ call assert_equal(['2222'], readfile('Xfile1'))
+ call delete('Xfile1')
+ call delete('Xfile2')
+
+ " With the 'backupcopy' set to 'breaksymlink', saving a hard link file
+ " should break the link.
+ set backupcopy=yes,breakhardlink
+ call writefile(['1111'], 'Xfile1')
+ silent !ln Xfile1 Xfile2
+ new Xfile2
+ call setline(1, ['2222'])
+ write
+ call assert_equal(['1111'], readfile('Xfile1'))
+ call assert_equal(['2222'], readfile('Xfile2'))
+ call delete('Xfile1')
+ call delete('Xfile2')
+
+ " If a backup file is already present, then a slightly modified filename
+ " should be used as the backup file. Try with 'backupcopy' set to 'yes' and
+ " 'no'.
+ %bw
+ call writefile(['aaaa'], 'Xfile')
+ call writefile(['bbbb'], 'Xfile.bak')
+ set backupcopy=yes backupext=.bak
+ new Xfile
+ call setline(1, ['cccc'])
+ write
+ close
+ call assert_equal(['cccc'], readfile('Xfile'))
+ call assert_equal(['bbbb'], readfile('Xfile.bak'))
+ set backupcopy=no backupext=.bak
+ new Xfile
+ call setline(1, ['dddd'])
+ write
+ close
+ call assert_equal(['dddd'], readfile('Xfile'))
+ call assert_equal(['bbbb'], readfile('Xfile.bak'))
+ call delete('Xfile')
+ call delete('Xfile.bak')
+
+ " Write to a device file (in Unix-like systems) which cannot be backed up.
+ if has('unix')
+ set writebackup backupcopy=yes nobackup
+ new
+ call setline(1, ['aaaa'])
+ let output = execute('write! /dev/null')
+ call assert_match('"/dev/null" \[Device]', output)
+ close
+ set writebackup backupcopy=no nobackup
+ new
+ call setline(1, ['aaaa'])
+ let output = execute('write! /dev/null')
+ call assert_match('"/dev/null" \[Device]', output)
+ close
+ set backup writebackup& backupcopy&
+ new
+ call setline(1, ['aaaa'])
+ let output = execute('write! /dev/null')
+ call assert_match('"/dev/null" \[Device]', output)
+ close
+ endif
+
+ set backupcopy& backupskip& backupext& backup&
+endfunc
+
+" Test for writing a file with 'encoding' set to 'utf-16'
+func Test_write_utf16()
+ new
+ call setline(1, ["\U00010001"])
+ write ++enc=utf-16 Xfile
+ bw!
+ call assert_equal(0zD800DC01, readfile('Xfile', 'B')[0:3])
+ call delete('Xfile')
+endfunc
+
+" Test for trying to save a backup file when the backup file is a symbolic
+" link to the original file. The backup file should not be modified.
+func Test_write_backup_symlink()
+ CheckUnix
+ call writefile(['1111'], 'Xfile')
+ silent !ln -s Xfile Xfile.bak
+
+ new Xfile
+ set backup backupcopy=yes backupext=.bak
+ write
+ call assert_equal('link', getftype('Xfile.bak'))
+ call assert_equal('Xfile', resolve('Xfile.bak'))
+ set backup& backupcopy& backupext&
+ close
+
+ call delete('Xfile')
+ call delete('Xfile.bak')
+endfunc
+
+" Test for ':write ++bin' and ':write ++nobin'
+func Test_write_binary_file()
+ " create a file without an eol/eof character
+ call writefile(0z616161, 'Xfile1', 'b')
+ new Xfile1
+ write ++bin Xfile2
+ write ++nobin Xfile3
+ call assert_equal(0z616161, readblob('Xfile2'))
+ if has('win32')
+ call assert_equal(0z6161610D.0A, readblob('Xfile3'))
+ else
+ call assert_equal(0z6161610A, readblob('Xfile3'))
+ endif
+ call delete('Xfile1')
+ call delete('Xfile2')
+ call delete('Xfile3')
+endfunc
+
" Check that buffer is written before triggering QuitPre
func Test_wq_quitpre_autocommand()
edit Xsomefile