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