neovim

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

test_writefile.vim (29214B)


      1 " Tests for the writefile() function and some :write commands.
      2 
      3 source check.vim
      4 source term_util.vim
      5 
      6 func Test_writefile()
      7  let f = tempname()
      8  call writefile(["over","written"], f, "b")
      9  call writefile(["hello","world"], f, "b")
     10  call writefile(["!", "good"], f, "a")
     11  call writefile(["morning"], f, "ab")
     12  call writefile(["", "vimmers"], f, "ab")
     13  let l = readfile(f)
     14  call assert_equal("hello", l[0])
     15  call assert_equal("world!", l[1])
     16  call assert_equal("good", l[2])
     17  call assert_equal("morning", l[3])
     18  call assert_equal("vimmers", l[4])
     19  call delete(f)
     20 
     21  call assert_fails('call writefile("text", "Xfile")', 'E475: Invalid argument: writefile() first argument must be a List or a Blob')
     22 endfunc
     23 
     24 func Test_writefile_ignore_regexp_error()
     25  write Xt[z-a]est.txt
     26  call delete('Xt[z-a]est.txt')
     27 endfunc
     28 
     29 func Test_writefile_fails_gently()
     30  call assert_fails('call writefile(["test"], "Xfile", [])', 'E730:')
     31  call assert_false(filereadable("Xfile"))
     32  call delete("Xfile")
     33 
     34  call assert_fails('call writefile(["test", [], [], [], "tset"], "Xfile")', 'E745:')
     35  call assert_false(filereadable("Xfile"))
     36  call delete("Xfile")
     37 
     38  call assert_fails('call writefile([], "Xfile", [])', 'E730:')
     39  call assert_false(filereadable("Xfile"))
     40  call delete("Xfile")
     41 
     42  call assert_fails('call writefile([], [])', 'E730:')
     43 endfunc
     44 
     45 func Test_writefile_fails_conversion()
     46  if !has('iconv') || has('sun')
     47    return
     48  endif
     49  " Without a backup file the write won't happen if there is a conversion
     50  " error.
     51  set nobackup nowritebackup backupdir=. backupskip=
     52  new
     53  let contents = ["line one", "line two"]
     54  call writefile(contents, 'Xfile')
     55  edit Xfile
     56  call setline(1, ["first line", "cannot convert \u010b", "third line"])
     57  call assert_fails('write ++enc=cp932', 'E513:')
     58  call assert_equal(contents, readfile('Xfile'))
     59 
     60  " With 'backupcopy' set, if there is a conversion error, the backup file is
     61  " still created.
     62  set backupcopy=yes writebackup& backup&
     63  call delete('Xfile' .. &backupext)
     64  call assert_fails('write ++enc=cp932', 'E513:')
     65  call assert_equal(contents, readfile('Xfile'))
     66  call assert_equal(contents, readfile('Xfile' .. &backupext))
     67  set backupcopy&
     68  %bw!
     69 
     70  " Conversion error during write
     71  new
     72  call setline(1, ["\U10000000"])
     73  let output = execute('write! ++enc=utf-16 Xfile')
     74  call assert_match('CONVERSION ERROR', output)
     75  let output = execute('write! ++enc=ucs-2 Xfile')
     76  call assert_match('CONVERSION ERROR', output)
     77  call delete('Xfilz~')
     78  call delete('Xfily~')
     79  %bw!
     80 
     81  call delete('Xfile')
     82  call delete('Xfile' .. &backupext)
     83  bwipe!
     84  set backup& writebackup& backupdir&vim backupskip&vim
     85 endfunc
     86 
     87 func Test_writefile_fails_conversion2()
     88  if !has('iconv') || has('sun')
     89    return
     90  endif
     91  " With a backup file the write happens even if there is a conversion error,
     92  " but then the backup file must remain
     93  set nobackup writebackup backupdir=. backupskip=
     94  let contents = ["line one", "line two"]
     95  call writefile(contents, 'Xfile_conversion_err')
     96  edit Xfile_conversion_err
     97  call setline(1, ["first line", "cannot convert \u010b", "third line"])
     98  set fileencoding=latin1
     99  let output = execute('write')
    100  call assert_match('CONVERSION ERROR', output)
    101  call assert_equal(contents, readfile('Xfile_conversion_err~'))
    102 
    103  call delete('Xfile_conversion_err')
    104  call delete('Xfile_conversion_err~')
    105  bwipe!
    106  set backup& writebackup& backupdir&vim backupskip&vim
    107 endfunc
    108 
    109 func SetFlag(timer)
    110  let g:flag = 1
    111 endfunc
    112 
    113 func Test_write_quit_split()
    114  " Prevent exiting by splitting window on file write.
    115  augroup testgroup
    116    autocmd BufWritePre * split
    117  augroup END
    118  e! Xfile
    119  call setline(1, 'nothing')
    120  wq
    121 
    122  if has('timers')
    123    " timer will not run if "exiting" is still set
    124    let g:flag = 0
    125    call timer_start(1, 'SetFlag')
    126    sleep 50m
    127    call assert_equal(1, g:flag)
    128    unlet g:flag
    129  endif
    130  au! testgroup
    131  bwipe Xfile
    132  call delete('Xfile')
    133 endfunc
    134 
    135 func Test_nowrite_quit_split()
    136  " Prevent exiting by opening a help window.
    137  e! Xfile
    138  help
    139  wincmd w
    140  exe winnr() . 'q'
    141 
    142  if has('timers')
    143    " timer will not run if "exiting" is still set
    144    let g:flag = 0
    145    call timer_start(1, 'SetFlag')
    146    sleep 50m
    147    call assert_equal(1, g:flag)
    148    unlet g:flag
    149  endif
    150  bwipe Xfile
    151 endfunc
    152 
    153 func Test_writefile_sync_arg()
    154  " This doesn't check if fsync() works, only that the argument is accepted.
    155  call writefile(['one'], 'Xtest', 's')
    156  call writefile(['two'], 'Xtest', 'S')
    157  call delete('Xtest')
    158 endfunc
    159 
    160 func Test_writefile_sync_dev_stdout()
    161  CheckUnix
    162  if filewritable('/dev/stdout')
    163    " Just check that this doesn't cause an error.
    164    call writefile(['one'], '/dev/stdout', 's')
    165  else
    166    throw 'Skipped: /dev/stdout is not writable'
    167  endif
    168 endfunc
    169 
    170 func Test_writefile_autowrite()
    171  set autowrite
    172  new
    173  next Xa Xb Xc
    174  call setline(1, 'aaa')
    175  next
    176  call assert_equal(['aaa'], readfile('Xa'))
    177  call setline(1, 'bbb')
    178  call assert_fails('edit XX', 'E37: No write since last change (add ! to override)')
    179  call assert_false(filereadable('Xb'))
    180 
    181  set autowriteall
    182  edit XX
    183  call assert_equal(['bbb'], readfile('Xb'))
    184 
    185  bwipe!
    186  call delete('Xa')
    187  call delete('Xb')
    188  set noautowrite
    189 endfunc
    190 
    191 func Test_writefile_autowrite_nowrite()
    192  set autowrite
    193  new
    194  next Xa Xb Xc
    195  set buftype=nowrite
    196  call setline(1, 'aaa')
    197  let buf = bufnr('%')
    198  " buffer contents silently lost
    199  edit XX
    200  call assert_false(filereadable('Xa'))
    201  rewind
    202  call assert_equal('', getline(1))
    203 
    204  bwipe!
    205  set noautowrite
    206 endfunc
    207 
    208 " Test for ':w !<cmd>' to pipe lines from the current buffer to an external
    209 " command.
    210 func Test_write_pipe_to_cmd()
    211  CheckUnix
    212  new
    213  call setline(1, ['L1', 'L2', 'L3', 'L4'])
    214  2,3w !cat > Xfile
    215  call assert_equal(['L2', 'L3'], readfile('Xfile'))
    216  close!
    217  call delete('Xfile')
    218 endfunc
    219 
    220 " Test for :saveas
    221 func Test_saveas()
    222  call assert_fails('saveas', 'E471:')
    223  call writefile(['L1'], 'Xfile')
    224  new Xfile
    225  new
    226  call setline(1, ['L1'])
    227  call assert_fails('saveas Xfile', 'E139:')
    228  close!
    229  enew | only
    230  call delete('Xfile')
    231 
    232  " :saveas should detect and set the file type.
    233  syntax on
    234  saveas! Xsaveas.pl
    235  call assert_equal('perl', &filetype)
    236  syntax off
    237  %bw!
    238  call delete('Xsaveas.pl')
    239 
    240  " :saveas fails for "nofile" buffer
    241  set buftype=nofile
    242  call assert_fails('saveas Xsafile', 'E676: No matching autocommands for buftype=nofile buffer')
    243 
    244  bwipe!
    245 endfunc
    246 
    247 func Test_write_errors()
    248  " Test for writing partial buffer
    249  call writefile(['L1', 'L2', 'L3'], 'Xfile')
    250  new Xfile
    251  call assert_fails('1,2write', 'E140:')
    252  close!
    253 
    254  call assert_fails('w > Xtest', 'E494:')
    255 
    256  " Try to overwrite a directory
    257  if has('unix')
    258    call mkdir('Xdir1')
    259    call assert_fails('write Xdir1', 'E17:')
    260    call delete('Xdir1', 'd')
    261  endif
    262 
    263  " Test for :wall for a buffer with no name
    264  enew | only
    265  call setline(1, ['L1'])
    266  call assert_fails('wall', 'E141:')
    267  enew!
    268 
    269  " Test for writing a 'readonly' file
    270  new Xfile
    271  set readonly
    272  call assert_fails('write', 'E45:')
    273  close
    274 
    275  " Test for writing to a read-only file
    276  new Xfile
    277  call setfperm('Xfile', 'r--r--r--')
    278  call assert_fails('write', 'E505:')
    279  call setfperm('Xfile', 'rw-rw-rw-')
    280  close
    281 
    282  call delete('Xfile')
    283 
    284  " Nvim treats NULL list/blob more like empty list/blob
    285  " call writefile(v:_null_list, 'Xfile')
    286  " call assert_false(filereadable('Xfile'))
    287  " call writefile(v:_null_blob, 'Xfile')
    288  " call assert_false(filereadable('Xfile'))
    289  call assert_fails('call writefile([], "")', 'E482:')
    290 
    291  " very long file name
    292  let long_fname = repeat('n', 5000)
    293  call assert_fails('exe "w " .. long_fname', 'E75:')
    294  call assert_fails('call writefile([], long_fname)', 'E482:')
    295 
    296  " Test for writing to a block device on Unix-like systems
    297  if has('unix') && getfperm('/dev/loop0') != ''
    298        \ && getftype('/dev/loop0') == 'bdev' && !IsRoot()
    299    new
    300    edit /dev/loop0
    301    call assert_fails('write', 'E503: ')
    302    call assert_fails('write!', 'E503: ')
    303    close!
    304  endif
    305 endfunc
    306 
    307 " Test for writing to a file which is modified after Vim read it
    308 func Test_write_file_mtime()
    309  CheckEnglish
    310  CheckRunVimInTerminal
    311 
    312  " First read the file into a buffer
    313  call writefile(["Line1", "Line2"], 'Xfile')
    314  let old_ftime = getftime('Xfile')
    315  let buf = RunVimInTerminal('Xfile', #{rows : 10})
    316  call term_wait(buf)
    317  call term_sendkeys(buf, ":set noswapfile\<CR>")
    318  call term_wait(buf)
    319 
    320  " Modify the file directly.  Make sure the file modification time is
    321  " different. Note that on Linux/Unix, the file is considered modified
    322  " outside, only if the difference is 2 seconds or more
    323  sleep 1
    324  call writefile(["Line3", "Line4"], 'Xfile')
    325  let new_ftime = getftime('Xfile')
    326  while new_ftime - old_ftime < 2
    327    sleep 100m
    328    call writefile(["Line3", "Line4"], 'Xfile')
    329    let new_ftime = getftime('Xfile')
    330  endwhile
    331 
    332  " Try to overwrite the file and check for the prompt
    333  call term_sendkeys(buf, ":w\<CR>")
    334  call term_wait(buf)
    335  call WaitForAssert({-> assert_equal("WARNING: The file has been changed since reading it!!!", term_getline(buf, 9))})
    336  call assert_equal("Do you really want to write to it (y/n)?",
    337        \ term_getline(buf, 10))
    338  call term_sendkeys(buf, "n\<CR>")
    339  call term_wait(buf)
    340  call assert_equal(new_ftime, getftime('Xfile'))
    341  call term_sendkeys(buf, ":w\<CR>")
    342  call term_wait(buf)
    343  call term_sendkeys(buf, "y\<CR>")
    344  call term_wait(buf)
    345  call WaitForAssert({-> assert_equal('Line2', readfile('Xfile')[1])})
    346 
    347  " clean up
    348  call StopVimInTerminal(buf)
    349  call delete('Xfile')
    350 endfunc
    351 
    352 " Test for an autocmd unloading a buffer during a write command
    353 func Test_write_autocmd_unloadbuf_lockmark()
    354  augroup WriteTest
    355    autocmd BufWritePre Xfile enew | write
    356  augroup END
    357  e Xfile
    358  call assert_fails('lockmarks write', ['E32', 'E203:'])
    359  augroup WriteTest
    360    au!
    361  augroup END
    362  augroup! WriteTest
    363 endfunc
    364 
    365 " Test for writing a buffer with 'acwrite' but without autocmds
    366 func Test_write_acwrite_error()
    367  new Xfile
    368  call setline(1, ['line1', 'line2', 'line3'])
    369  set buftype=acwrite
    370  call assert_fails('write', 'E676:')
    371  call assert_fails('1,2write!', 'E676:')
    372  call assert_fails('w >>', 'E676:')
    373  close!
    374 endfunc
    375 
    376 " Test for adding and removing lines from an autocmd when writing a buffer
    377 func Test_write_autocmd_add_remove_lines()
    378  new Xfile
    379  call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
    380 
    381  " Autocmd deleting lines from the file when writing a partial file
    382  augroup WriteTest2
    383    au!
    384    autocmd FileWritePre Xfile 1,2d
    385  augroup END
    386  call assert_fails('2,3w!', 'E204:')
    387 
    388  " Autocmd adding lines to a file when writing a partial file
    389  augroup WriteTest2
    390    au!
    391    autocmd FileWritePre Xfile call append(0, ['xxx', 'yyy'])
    392  augroup END
    393  %d
    394  call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
    395  1,2w!
    396  call assert_equal(['xxx', 'yyy', 'aaa', 'bbb'], readfile('Xfile'))
    397 
    398  " Autocmd deleting lines from the file when writing the whole file
    399  augroup WriteTest2
    400    au!
    401    autocmd BufWritePre Xfile 1,2d
    402  augroup END
    403  %d
    404  call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
    405  w
    406  call assert_equal(['ccc', 'ddd'], readfile('Xfile'))
    407 
    408  augroup WriteTest2
    409    au!
    410  augroup END
    411  augroup! WriteTest2
    412 
    413  close!
    414  call delete('Xfile')
    415 endfunc
    416 
    417 " Test for writing to a readonly file
    418 func Test_write_readonly()
    419  call writefile([], 'Xfile')
    420  call setfperm('Xfile', "r--------")
    421  edit Xfile
    422  set noreadonly backupskip=
    423  call assert_fails('write', 'E505:')
    424  let save_cpo = &cpo
    425  set cpo+=W
    426  call assert_fails('write!', 'E504:')
    427  let &cpo = save_cpo
    428  call setline(1, ['line1'])
    429  write!
    430  call assert_equal(['line1'], readfile('Xfile'))
    431 
    432  " Auto-saving a readonly file should fail with 'autowriteall'
    433  %bw!
    434  e Xfile
    435  set noreadonly autowriteall
    436  call setline(1, ['aaaa'])
    437  call assert_fails('n', 'E505:')
    438  set cpo+=W
    439  call assert_fails('n', 'E504:')
    440  set cpo-=W
    441  set autowriteall&
    442 
    443  set backupskip&
    444  call delete('Xfile')
    445  %bw!
    446 endfunc
    447 
    448 " Test for 'patchmode'
    449 func Test_patchmode()
    450  call writefile(['one'], 'Xfile')
    451  set patchmode=.orig nobackup backupskip= writebackup
    452  new Xfile
    453  call setline(1, 'two')
    454  " first write should create the .orig file
    455  write
    456  call assert_equal(['one'], readfile('Xfile.orig'))
    457  call setline(1, 'three')
    458  " subsequent writes should not create/modify the .orig file
    459  write
    460  call assert_equal(['one'], readfile('Xfile.orig'))
    461 
    462  " use 'patchmode' with 'nobackup' and 'nowritebackup' to create an empty
    463  " original file
    464  call delete('Xfile')
    465  call delete('Xfile.orig')
    466  %bw!
    467  set patchmode=.orig nobackup nowritebackup
    468  edit Xfile
    469  call setline(1, ['xxx'])
    470  write
    471  call assert_equal(['xxx'], readfile('Xfile'))
    472  call assert_equal([], readfile('Xfile.orig'))
    473 
    474  set patchmode& backup& backupskip& writebackup&
    475  call delete('Xfile')
    476  call delete('Xfile.orig')
    477 endfunc
    478 
    479 " Test for writing to a file in a readonly directory
    480 " NOTE: if you run tests as root this will fail.  Don't run tests as root!
    481 func Test_write_readonly_dir()
    482  " On MS-Windows, modifying files in a read-only directory is allowed.
    483  CheckUnix
    484  " Root can do it too.
    485  CheckNotRoot
    486 
    487  call mkdir('Xdir/')
    488  call writefile(['one'], 'Xdir/Xfile1')
    489  call setfperm('Xdir', 'r-xr--r--')
    490  " try to create a new file in the directory
    491  new Xdir/Xfile2
    492  call setline(1, 'two')
    493  call assert_fails('write', 'E212:')
    494  " try to create a backup file in the directory
    495  edit! Xdir/Xfile1
    496  set backupdir=./Xdir backupskip=
    497  set patchmode=.orig
    498  call assert_fails('write', 'E509:')
    499  call setfperm('Xdir', 'rwxr--r--')
    500  call delete('Xdir', 'rf')
    501  set backupdir& backupskip& patchmode&
    502 endfunc
    503 
    504 " Test for writing a file using invalid file encoding
    505 func Test_write_invalid_encoding()
    506  new
    507  call setline(1, 'abc')
    508  call assert_fails('write ++enc=axbyc Xfile', 'E213:')
    509  close!
    510 endfunc
    511 
    512 " Tests for reading and writing files with conversion for Win32.
    513 func Test_write_file_encoding()
    514  throw 'Skipped: Nvim does not support encoding=latin1'
    515  CheckMSWindows
    516  let save_encoding = &encoding
    517  let save_fileencodings = &fileencodings
    518  set encoding=latin1 fileencodings&
    519  let text =<< trim END
    520    1 utf-8 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    521    2 cp1251 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    522    3 cp866 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    523  END
    524  call writefile(text, 'Xfile')
    525  edit Xfile
    526 
    527  " write tests:
    528  " combine three values for 'encoding' with three values for 'fileencoding'
    529  " also write files for read tests
    530  call cursor(1, 1)
    531  set encoding=utf-8
    532  .w! ++enc=utf-8 Xtest
    533  .w ++enc=cp1251 >> Xtest
    534  .w ++enc=cp866 >> Xtest
    535  .w! ++enc=utf-8 Xutf8
    536  let expected =<< trim END
    537    1 utf-8 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    538    1 utf-8 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    539    1 utf-8 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    540  END
    541  call assert_equal(expected, readfile('Xtest'))
    542 
    543  call cursor(2, 1)
    544  set encoding=cp1251
    545  .w! ++enc=utf-8 Xtest
    546  .w ++enc=cp1251 >> Xtest
    547  .w ++enc=cp866 >> Xtest
    548  .w! ++enc=cp1251 Xcp1251
    549  let expected =<< trim END
    550    2 cp1251 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    551    2 cp1251 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    552    2 cp1251 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    553  END
    554  call assert_equal(expected, readfile('Xtest'))
    555 
    556  call cursor(3, 1)
    557  set encoding=cp866
    558  .w! ++enc=utf-8 Xtest
    559  .w ++enc=cp1251 >> Xtest
    560  .w ++enc=cp866 >> Xtest
    561  .w! ++enc=cp866 Xcp866
    562  let expected =<< trim END
    563    3 cp866 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    564    3 cp866 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    565    3 cp866 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    566  END
    567  call assert_equal(expected, readfile('Xtest'))
    568 
    569  " read three 'fileencoding's with utf-8 'encoding'
    570  set encoding=utf-8 fencs=utf-8,cp1251
    571  e Xutf8
    572  .w! ++enc=utf-8 Xtest
    573  e Xcp1251
    574  .w ++enc=utf-8 >> Xtest
    575  set fencs=utf-8,cp866
    576  e Xcp866
    577  .w ++enc=utf-8 >> Xtest
    578  let expected =<< trim END
    579    1 utf-8 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    580    2 cp1251 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    581    3 cp866 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
    582  END
    583  call assert_equal(expected, readfile('Xtest'))
    584 
    585  " read three 'fileencoding's with cp1251 'encoding'
    586  set encoding=utf-8 fencs=utf-8,cp1251
    587  e Xutf8
    588  .w! ++enc=cp1251 Xtest
    589  e Xcp1251
    590  .w ++enc=cp1251 >> Xtest
    591  set fencs=utf-8,cp866
    592  e Xcp866
    593  .w ++enc=cp1251 >> Xtest
    594  let expected =<< trim END
    595    1 utf-8 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    596    2 cp1251 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    597    3 cp866 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
    598  END
    599  call assert_equal(expected, readfile('Xtest'))
    600 
    601  " read three 'fileencoding's with cp866 'encoding'
    602  set encoding=cp866 fencs=utf-8,cp1251
    603  e Xutf8
    604  .w! ++enc=cp866 Xtest
    605  e Xcp1251
    606  .w ++enc=cp866 >> Xtest
    607  set fencs=utf-8,cp866
    608  e Xcp866
    609  .w ++enc=cp866 >> Xtest
    610  let expected =<< trim END
    611    1 utf-8 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    612    2 cp1251 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    613    3 cp866 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
    614  END
    615  call assert_equal(expected, readfile('Xtest'))
    616 
    617  call delete('Xfile')
    618  call delete('Xtest')
    619  call delete('Xutf8')
    620  call delete('Xcp1251')
    621  call delete('Xcp866')
    622  let &encoding = save_encoding
    623  let &fileencodings = save_fileencodings
    624  %bw!
    625 endfunc
    626 
    627 " Test for writing and reading a file starting with a BOM.
    628 " Byte Order Mark (BOM) character for various encodings is below:
    629 "     UTF-8      : EF BB BF
    630 "     UTF-16 (BE): FE FF
    631 "     UTF-16 (LE): FF FE
    632 "     UTF-32 (BE): 00 00 FE FF
    633 "     UTF-32 (LE): FF FE 00 00
    634 func Test_readwrite_file_with_bom()
    635  let utf8_bom = "\xEF\xBB\xBF"
    636  let utf16be_bom = "\xFE\xFF"
    637  let utf16le_bom = "\xFF\xFE"
    638  let utf32be_bom = "\n\n\xFE\xFF"
    639  let utf32le_bom = "\xFF\xFE\n\n"
    640  let save_fileencoding = &fileencoding
    641  set cpoptions+=S
    642 
    643  " Check that editing a latin1 file doesn't see a BOM
    644  call writefile(["\xFE\xFElatin-1"], 'Xtest1')
    645  edit Xtest1
    646  call assert_equal('latin1', &fileencoding)
    647  call assert_equal(0, &bomb)
    648  set fenc=latin1
    649  write Xfile2
    650  call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xfile2', 'b'))
    651  set bomb fenc=latin1
    652  write Xtest3
    653  call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xtest3', 'b'))
    654  set bomb&
    655 
    656  " Check utf-8 BOM
    657  %bw!
    658  call writefile([utf8_bom .. "utf-8"], 'Xtest1')
    659  edit! Xtest1
    660  call assert_equal('utf-8', &fileencoding)
    661  call assert_equal(1, &bomb)
    662  call assert_equal('utf-8', getline(1))
    663  set fenc=latin1
    664  write! Xfile2
    665  call assert_equal(['utf-8', ''], readfile('Xfile2', 'b'))
    666  set fenc=utf-8
    667  w! Xtest3
    668  call assert_equal([utf8_bom .. "utf-8", ''], readfile('Xtest3', 'b'))
    669 
    670  " Check utf-8 with an error (will fall back to latin-1)
    671  %bw!
    672  call writefile([utf8_bom .. "utf-8\x80err"], 'Xtest1')
    673  edit! Xtest1
    674  call assert_equal('latin1', &fileencoding)
    675  call assert_equal(0, &bomb)
    676  call assert_equal("\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", getline(1))
    677  set fenc=latin1
    678  write! Xfile2
    679  call assert_equal([utf8_bom .. "utf-8\x80err", ''], readfile('Xfile2', 'b'))
    680  set fenc=utf-8
    681  w! Xtest3
    682  call assert_equal(["\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", ''],
    683        \ readfile('Xtest3', 'b'))
    684 
    685  " Check ucs-2 BOM
    686  %bw!
    687  call writefile([utf16be_bom .. "\nu\nc\ns\n-\n2\n"], 'Xtest1')
    688  edit! Xtest1
    689  call assert_equal('utf-16', &fileencoding)
    690  call assert_equal(1, &bomb)
    691  call assert_equal('ucs-2', getline(1))
    692  set fenc=latin1
    693  write! Xfile2
    694  call assert_equal(["ucs-2", ''], readfile('Xfile2', 'b'))
    695  set fenc=ucs-2
    696  w! Xtest3
    697  call assert_equal([utf16be_bom .. "\nu\nc\ns\n-\n2\n", ''],
    698        \ readfile('Xtest3', 'b'))
    699 
    700  " Check ucs-2le BOM
    701  %bw!
    702  call writefile([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n"], 'Xtest1')
    703  " Need to add a NUL byte after the NL byte
    704  call writefile(0z00, 'Xtest1', 'a')
    705  edit! Xtest1
    706  call assert_equal('utf-16le', &fileencoding)
    707  call assert_equal(1, &bomb)
    708  call assert_equal('ucs-2le', getline(1))
    709  set fenc=latin1
    710  write! Xfile2
    711  call assert_equal(["ucs-2le", ''], readfile('Xfile2', 'b'))
    712  set fenc=ucs-2le
    713  w! Xtest3
    714  call assert_equal([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n", "\n"],
    715        \ readfile('Xtest3', 'b'))
    716 
    717  " Check ucs-4 BOM
    718  %bw!
    719  call writefile([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n"], 'Xtest1')
    720  edit! Xtest1
    721  call assert_equal('ucs-4', &fileencoding)
    722  call assert_equal(1, &bomb)
    723  call assert_equal('ucs-4', getline(1))
    724  set fenc=latin1
    725  write! Xfile2
    726  call assert_equal(["ucs-4", ''], readfile('Xfile2', 'b'))
    727  set fenc=ucs-4
    728  w! Xtest3
    729  call assert_equal([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n", ''], readfile('Xtest3', 'b'))
    730 
    731  " Check ucs-4le BOM
    732  %bw!
    733  call writefile([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n"], 'Xtest1')
    734  " Need to add three NUL bytes after the NL byte
    735  call writefile(0z000000, 'Xtest1', 'a')
    736  edit! Xtest1
    737  call assert_equal('ucs-4le', &fileencoding)
    738  call assert_equal(1, &bomb)
    739  call assert_equal('ucs-4le', getline(1))
    740  set fenc=latin1
    741  write! Xfile2
    742  call assert_equal(["ucs-4le", ''], readfile('Xfile2', 'b'))
    743  set fenc=ucs-4le
    744  w! Xtest3
    745  call assert_equal([utf32le_bom .. "u\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\nl\n\n\ne\n\n\n", "\n\n\n"], readfile('Xtest3', 'b'))
    746 
    747  set cpoptions-=S
    748  let &fileencoding = save_fileencoding
    749  call delete('Xtest1')
    750  call delete('Xfile2')
    751  call delete('Xtest3')
    752  %bw!
    753 endfunc
    754 
    755 func Test_read_write_bin()
    756  " write file missing EOL
    757  call writefile(['noeol'], "XNoEolSetEol", 'bS')
    758  call assert_equal(0z6E6F656F6C, readfile('XNoEolSetEol', 'B'))
    759 
    760  " when file is read 'eol' is off
    761  set nofixeol
    762  e! ++ff=unix XNoEolSetEol
    763  call assert_equal(0, &eol)
    764 
    765  " writing with 'eol' set adds the newline
    766  setlocal eol
    767  w
    768  call assert_equal(0z6E6F656F6C0A, readfile('XNoEolSetEol', 'B'))
    769 
    770  call delete('XNoEolSetEol')
    771  set ff& fixeol&
    772  bwipe! XNoEolSetEol
    773 endfunc
    774 
    775 " Test for the 'backupcopy' option when writing files
    776 func Test_backupcopy()
    777  CheckUnix
    778  set backupskip=
    779  " With the default 'backupcopy' setting, saving a symbolic link file
    780  " should not break the link.
    781  set backupcopy&
    782  call writefile(['1111'], 'Xfile1')
    783  silent !ln -s Xfile1 Xfile2
    784  new Xfile2
    785  call setline(1, ['2222'])
    786  write
    787  close
    788  call assert_equal(['2222'], readfile('Xfile1'))
    789  call assert_equal('Xfile1', resolve('Xfile2'))
    790  call assert_equal('link', getftype('Xfile2'))
    791  call delete('Xfile1')
    792  call delete('Xfile2')
    793 
    794  " With the 'backupcopy' set to 'breaksymlink', saving a symbolic link file
    795  " should break the link.
    796  set backupcopy=yes,breaksymlink
    797  call writefile(['1111'], 'Xfile1')
    798  silent !ln -s Xfile1 Xfile2
    799  new Xfile2
    800  call setline(1, ['2222'])
    801  write
    802  close
    803  call assert_equal(['1111'], readfile('Xfile1'))
    804  call assert_equal(['2222'], readfile('Xfile2'))
    805  call assert_equal('Xfile2', resolve('Xfile2'))
    806  call assert_equal('file', getftype('Xfile2'))
    807  call delete('Xfile1')
    808  call delete('Xfile2')
    809  set backupcopy&
    810 
    811  " With the default 'backupcopy' setting, saving a hard link file
    812  " should not break the link.
    813  set backupcopy&
    814  call writefile(['1111'], 'Xfile1')
    815  silent !ln Xfile1 Xfile2
    816  new Xfile2
    817  call setline(1, ['2222'])
    818  write
    819  close
    820  call assert_equal(['2222'], readfile('Xfile1'))
    821  call delete('Xfile1')
    822  call delete('Xfile2')
    823 
    824  " With the 'backupcopy' set to 'breaksymlink', saving a hard link file
    825  " should break the link.
    826  set backupcopy=yes,breakhardlink
    827  call writefile(['1111'], 'Xfile1')
    828  silent !ln Xfile1 Xfile2
    829  new Xfile2
    830  call setline(1, ['2222'])
    831  write
    832  call assert_equal(['1111'], readfile('Xfile1'))
    833  call assert_equal(['2222'], readfile('Xfile2'))
    834  call delete('Xfile1')
    835  call delete('Xfile2')
    836 
    837  " If a backup file is already present, then a slightly modified filename
    838  " should be used as the backup file. Try with 'backupcopy' set to 'yes' and
    839  " 'no'.
    840  %bw
    841  call writefile(['aaaa'], 'Xfile')
    842  call writefile(['bbbb'], 'Xfile.bak')
    843  set backupcopy=yes backupext=.bak
    844  new Xfile
    845  call setline(1, ['cccc'])
    846  write
    847  close
    848  call assert_equal(['cccc'], readfile('Xfile'))
    849  call assert_equal(['bbbb'], readfile('Xfile.bak'))
    850  set backupcopy=no backupext=.bak
    851  new Xfile
    852  call setline(1, ['dddd'])
    853  write
    854  close
    855  call assert_equal(['dddd'], readfile('Xfile'))
    856  call assert_equal(['bbbb'], readfile('Xfile.bak'))
    857  call delete('Xfile')
    858  call delete('Xfile.bak')
    859 
    860  " Write to a device file (in Unix-like systems) which cannot be backed up.
    861  if has('unix')
    862    set writebackup backupcopy=yes nobackup
    863    new
    864    call setline(1, ['aaaa'])
    865    let output = execute('write! /dev/null')
    866    call assert_match('"/dev/null" \[Device]', output)
    867    close
    868    set writebackup backupcopy=no nobackup
    869    new
    870    call setline(1, ['aaaa'])
    871    let output = execute('write! /dev/null')
    872    call assert_match('"/dev/null" \[Device]', output)
    873    close
    874    set backup writebackup& backupcopy&
    875    new
    876    call setline(1, ['aaaa'])
    877    let output = execute('write! /dev/null')
    878    call assert_match('"/dev/null" \[Device]', output)
    879    close
    880  endif
    881 
    882  set backupcopy& backupskip& backupext& backup&
    883 endfunc
    884 
    885 " Test for writing a file with 'encoding' set to 'utf-16'
    886 func Test_write_utf16()
    887  new
    888  call setline(1, ["\U00010001"])
    889  write ++enc=utf-16 Xfile
    890  bw!
    891  call assert_equal(0zD800DC01, readfile('Xfile', 'B')[0:3])
    892  call delete('Xfile')
    893 endfunc
    894 
    895 " Test for trying to save a backup file when the backup file is a symbolic
    896 " link to the original file. The backup file should not be modified.
    897 func Test_write_backup_symlink()
    898  CheckUnix
    899  call mkdir('Xbackup')
    900  let save_backupdir = &backupdir
    901  set backupdir=.,./Xbackup
    902  call writefile(['1111'], 'Xfile')
    903  silent !ln -s Xfile Xfile.bak
    904 
    905  new Xfile
    906  set backup backupcopy=yes backupext=.bak
    907  write
    908  call assert_equal('link', getftype('Xfile.bak'))
    909  call assert_equal('Xfile', resolve('Xfile.bak'))
    910  " backup file should be created in the 'backup' directory
    911  if !has('bsd')
    912    " This check fails on FreeBSD
    913    call assert_true(filereadable('./Xbackup/Xfile.bak'))
    914  endif
    915  set backup& backupcopy& backupext&
    916  %bw
    917 
    918  call delete('Xfile')
    919  call delete('Xfile.bak')
    920  call delete('Xbackup', 'rf')
    921  let &backupdir = save_backupdir
    922 endfunc
    923 
    924 " Test for ':write ++bin' and ':write ++nobin'
    925 func Test_write_binary_file()
    926  " create a file without an eol/eof character
    927  call writefile(0z616161, 'Xwbfile1', 'b')
    928  new Xwbfile1
    929  write ++bin Xwbfile2
    930  write ++nobin Xwbfile3
    931  call assert_equal(0z616161, readblob('Xwbfile2'))
    932  if has('win32')
    933    call assert_equal(0z6161610D.0A, readblob('Xwbfile3'))
    934  else
    935    call assert_equal(0z6161610A, readblob('Xwbfile3'))
    936  endif
    937  call delete('Xwbfile1')
    938  call delete('Xwbfile2')
    939  call delete('Xwbfile3')
    940 endfunc
    941 
    942 func DoWriteDefer()
    943  call writefile(['some text'], 'XdeferDelete', 'D')
    944  call assert_equal(['some text'], readfile('XdeferDelete'))
    945 endfunc
    946 
    947 " def DefWriteDefer()
    948 "   writefile(['some text'], 'XdefdeferDelete', 'D')
    949 "   assert_equal(['some text'], readfile('XdefdeferDelete'))
    950 " enddef
    951 
    952 func Test_write_with_deferred_delete()
    953  call DoWriteDefer()
    954  call assert_equal('', glob('XdeferDelete'))
    955  " call DefWriteDefer()
    956  " call assert_equal('', glob('XdefdeferDelete'))
    957 endfunc
    958 
    959 func DoWriteFile()
    960  call writefile(['text'], 'Xthefile', 'D')
    961  cd ..
    962 endfunc
    963 
    964 func Test_write_defer_delete_chdir()
    965  let dir = getcwd()
    966  call DoWriteFile()
    967  call assert_notequal(dir, getcwd())
    968  call chdir(dir)
    969  call assert_equal('', glob('Xthefile'))
    970 endfunc
    971 
    972 " Check that buffer is written before triggering QuitPre
    973 func Test_wq_quitpre_autocommand()
    974  edit Xsomefile
    975  call setline(1, 'hello')
    976  split
    977  let g:seq = []
    978  augroup Testing
    979    au QuitPre * call add(g:seq, 'QuitPre - ' .. (&modified ? 'modified' : 'not modified'))
    980    au BufWritePost * call add(g:seq, 'written')
    981  augroup END
    982  wq
    983  call assert_equal(['written', 'QuitPre - not modified'], g:seq)
    984 
    985  augroup Testing
    986    au!
    987  augroup END
    988  bwipe!
    989  unlet g:seq
    990  call delete('Xsomefile')
    991 endfunc
    992 
    993 func Test_write_with_xattr_support()
    994  CheckLinux
    995  CheckFeature xattr
    996  CheckExecutable setfattr
    997 
    998  let contents = ["file with xattrs", "line two"]
    999  call writefile(contents, 'Xwattr.txt', 'D')
   1000  " write a couple of xattr
   1001  call system('setfattr -n user.cookie -v chocolate Xwattr.txt')
   1002  call system('setfattr -n user.frieda -v bar Xwattr.txt')
   1003  call system('setfattr -n user.empty Xwattr.txt')
   1004 
   1005  set backupcopy=no writebackup& backup&
   1006  sp Xwattr.txt
   1007  w
   1008  $r! getfattr -d %
   1009  let expected = ['file with xattrs', 'line two', '# file: Xwattr.txt', 'user.cookie="chocolate"', 'user.empty=""', 'user.frieda="bar"', '']
   1010  call assert_equal(expected, getline(1,'$'))
   1011 
   1012  set backupcopy&
   1013  bw!
   1014 endfunc
   1015 
   1016 " vim: shiftwidth=2 sts=2 expandtab