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')
233
234  " :saveas should detect and set the file type.
235  syntax on
236  saveas! Xsaveas.pl
237  call assert_equal('perl', &filetype)
238  syntax off
239  %bw!
240  call delete('Xsaveas.pl')
241endfunc
242
243func Test_write_errors()
244  " Test for writing partial buffer
245  call writefile(['L1', 'L2', 'L3'], 'Xfile')
246  new Xfile
247  call assert_fails('1,2write', 'E140:')
248  close!
249
250  call assert_fails('w > Xtest', 'E494:')
251
252  " Try to overwrite a directory
253  if has('unix')
254    call mkdir('Xdir1')
255    call assert_fails('write Xdir1', 'E17:')
256    call delete('Xdir1', 'd')
257  endif
258
259  " Test for :wall for a buffer with no name
260  enew | only
261  call setline(1, ['L1'])
262  call assert_fails('wall', 'E141:')
263  enew!
264
265  " Test for writing a 'readonly' file
266  new Xfile
267  set readonly
268  call assert_fails('write', 'E45:')
269  close
270
271  " Test for writing to a read-only file
272  new Xfile
273  call setfperm('Xfile', 'r--r--r--')
274  call assert_fails('write', 'E505:')
275  call setfperm('Xfile', 'rw-rw-rw-')
276  close
277
278  call delete('Xfile')
279
280  call writefile(test_null_list(), 'Xfile')
281  call assert_false(filereadable('Xfile'))
282  call writefile(test_null_blob(), 'Xfile')
283  call assert_false(filereadable('Xfile'))
284  call assert_fails('call writefile([], "")', 'E482:')
285
286  " very long file name
287  let long_fname = repeat('n', 5000)
288  call assert_fails('exe "w " .. long_fname', 'E75:')
289  call assert_fails('call writefile([], long_fname)', 'E482:')
290
291  " Test for writing to a block device on Unix-like systems
292  if has('unix') && getfperm('/dev/loop0') != ''
293        \ && getftype('/dev/loop0') == 'bdev' && !IsRoot()
294    new
295    edit /dev/loop0
296    call assert_fails('write', 'E503: ')
297    call assert_fails('write!', 'E503: ')
298    close!
299  endif
300endfunc
301
302" Test for writing to a file which is modified after Vim read it
303func Test_write_file_mtime()
304  CheckEnglish
305  CheckRunVimInTerminal
306
307  " First read the file into a buffer
308  call writefile(["Line1", "Line2"], 'Xfile')
309  let old_ftime = getftime('Xfile')
310  let buf = RunVimInTerminal('Xfile', #{rows : 10})
311  call TermWait(buf)
312  call term_sendkeys(buf, ":set noswapfile\<CR>")
313  call TermWait(buf)
314
315  " Modify the file directly.  Make sure the file modification time is
316  " different. Note that on Linux/Unix, the file is considered modified
317  " outside, only if the difference is 2 seconds or more
318  sleep 1
319  call writefile(["Line3", "Line4"], 'Xfile')
320  let new_ftime = getftime('Xfile')
321  while new_ftime - old_ftime < 2
322    sleep 100m
323    call writefile(["Line3", "Line4"], 'Xfile')
324    let new_ftime = getftime('Xfile')
325  endwhile
326
327  " Try to overwrite the file and check for the prompt
328  call term_sendkeys(buf, ":w\<CR>")
329  call TermWait(buf)
330  call WaitForAssert({-> assert_equal("WARNING: The file has been changed since reading it!!!", term_getline(buf, 9))})
331  call assert_equal("Do you really want to write to it (y/n)?",
332        \ term_getline(buf, 10))
333  call term_sendkeys(buf, "n\<CR>")
334  call TermWait(buf)
335  call assert_equal(new_ftime, getftime('Xfile'))
336  call term_sendkeys(buf, ":w\<CR>")
337  call TermWait(buf)
338  call term_sendkeys(buf, "y\<CR>")
339  call TermWait(buf)
340  call WaitForAssert({-> assert_equal('Line2', readfile('Xfile')[1])})
341
342  " clean up
343  call StopVimInTerminal(buf)
344  call delete('Xfile')
345endfunc
346
347" Test for an autocmd unloading a buffer during a write command
348func Test_write_autocmd_unloadbuf_lockmark()
349  augroup WriteTest
350    autocmd BufWritePre Xfile enew | write
351  augroup END
352  e Xfile
353  call assert_fails('lockmarks write', ['E32:', 'E203:'])
354  augroup WriteTest
355    au!
356  augroup END
357  augroup! WriteTest
358endfunc
359
360" Test for writing a buffer with 'acwrite' but without autocmds
361func Test_write_acwrite_error()
362  new Xfile
363  call setline(1, ['line1', 'line2', 'line3'])
364  set buftype=acwrite
365  call assert_fails('write', 'E676:')
366  call assert_fails('1,2write!', 'E676:')
367  call assert_fails('w >>', 'E676:')
368  close!
369endfunc
370
371" Test for adding and removing lines from an autocmd when writing a buffer
372func Test_write_autocmd_add_remove_lines()
373  new Xfile
374  call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
375
376  " Autocmd deleting lines from the file when writing a partial file
377  augroup WriteTest2
378    au!
379    autocmd FileWritePre Xfile 1,2d
380  augroup END
381  call assert_fails('2,3w!', 'E204:')
382
383  " Autocmd adding lines to a file when writing a partial file
384  augroup WriteTest2
385    au!
386    autocmd FileWritePre Xfile call append(0, ['xxx', 'yyy'])
387  augroup END
388  %d
389  call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
390  1,2w!
391  call assert_equal(['xxx', 'yyy', 'aaa', 'bbb'], readfile('Xfile'))
392
393  " Autocmd deleting lines from the file when writing the whole file
394  augroup WriteTest2
395    au!
396    autocmd BufWritePre Xfile 1,2d
397  augroup END
398  %d
399  call setline(1, ['aaa', 'bbb', 'ccc', 'ddd'])
400  w
401  call assert_equal(['ccc', 'ddd'], readfile('Xfile'))
402
403  augroup WriteTest2
404    au!
405  augroup END
406  augroup! WriteTest2
407
408  close!
409  call delete('Xfile')
410endfunc
411
412" Test for writing to a readonly file
413func Test_write_readonly()
414  call writefile([], 'Xfile')
415  call setfperm('Xfile', "r--------")
416  edit Xfile
417  set noreadonly backupskip=
418  call assert_fails('write', 'E505:')
419  let save_cpo = &cpo
420  set cpo+=W
421  call assert_fails('write!', 'E504:')
422  let &cpo = save_cpo
423  call setline(1, ['line1'])
424  write!
425  call assert_equal(['line1'], readfile('Xfile'))
426
427  " Auto-saving a readonly file should fail with 'autowriteall'
428  %bw!
429  e Xfile
430  set noreadonly autowriteall
431  call setline(1, ['aaaa'])
432  call assert_fails('n', 'E505:')
433  set cpo+=W
434  call assert_fails('n', 'E504:')
435  set cpo-=W
436  set autowriteall&
437
438  set backupskip&
439  call delete('Xfile')
440  %bw!
441endfunc
442
443" Test for 'patchmode'
444func Test_patchmode()
445  call writefile(['one'], 'Xfile')
446  set patchmode=.orig nobackup backupskip= writebackup
447  new Xfile
448  call setline(1, 'two')
449  " first write should create the .orig file
450  write
451  call assert_equal(['one'], readfile('Xfile.orig'))
452  call setline(1, 'three')
453  " subsequent writes should not create/modify the .orig file
454  write
455  call assert_equal(['one'], readfile('Xfile.orig'))
456
457  " use 'patchmode' with 'nobackup' and 'nowritebackup' to create an empty
458  " original file
459  call delete('Xfile')
460  call delete('Xfile.orig')
461  %bw!
462  set patchmode=.orig nobackup nowritebackup
463  edit Xfile
464  call setline(1, ['xxx'])
465  write
466  call assert_equal(['xxx'], readfile('Xfile'))
467  call assert_equal([], readfile('Xfile.orig'))
468
469  set patchmode& backup& backupskip& writebackup&
470  call delete('Xfile')
471  call delete('Xfile.orig')
472endfunc
473
474" Test for writing to a file in a readonly directory
475" NOTE: if you run tests as root this will fail.  Don't run tests as root!
476func Test_write_readonly_dir()
477  " On MS-Windows, modifying files in a read-only directory is allowed.
478  CheckUnix
479  " Root can do it too.
480  CheckNotRoot
481
482  call mkdir('Xdir/')
483  call writefile(['one'], 'Xdir/Xfile1')
484  call setfperm('Xdir', 'r-xr--r--')
485  " try to create a new file in the directory
486  new Xdir/Xfile2
487  call setline(1, 'two')
488  call assert_fails('write', 'E212:')
489  " try to create a backup file in the directory
490  edit! Xdir/Xfile1
491  set backupdir=./Xdir backupskip=
492  set patchmode=.orig
493  call assert_fails('write', 'E509:')
494  call setfperm('Xdir', 'rwxr--r--')
495  call delete('Xdir', 'rf')
496  set backupdir& backupskip& patchmode&
497endfunc
498
499" Test for writing a file using invalid file encoding
500func Test_write_invalid_encoding()
501  new
502  call setline(1, 'abc')
503  call assert_fails('write ++enc=axbyc Xfile', 'E213:')
504  close!
505endfunc
506
507" Tests for reading and writing files with conversion for Win32.
508func Test_write_file_encoding()
509  CheckMSWindows
510  let save_encoding = &encoding
511  let save_fileencodings = &fileencodings
512  set encoding=latin1 fileencodings&
513  let text =<< trim END
514    1 utf-8 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
515    2 cp1251 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
516    3 cp866 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
517  END
518  call writefile(text, 'Xfile')
519  edit Xfile
520
521  " write tests:
522  " combine three values for 'encoding' with three values for 'fileencoding'
523  " also write files for read tests
524  call cursor(1, 1)
525  set encoding=utf-8
526  .w! ++enc=utf-8 Xtest
527  .w ++enc=cp1251 >> Xtest
528  .w ++enc=cp866 >> Xtest
529  .w! ++enc=utf-8 Xutf8
530  let expected =<< trim END
531    1 utf-8 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
532    1 utf-8 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
533    1 utf-8 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
534  END
535  call assert_equal(expected, readfile('Xtest'))
536
537  call cursor(2, 1)
538  set encoding=cp1251
539  .w! ++enc=utf-8 Xtest
540  .w ++enc=cp1251 >> Xtest
541  .w ++enc=cp866 >> Xtest
542  .w! ++enc=cp1251 Xcp1251
543  let expected =<< trim END
544    2 cp1251 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
545    2 cp1251 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
546    2 cp1251 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
547  END
548  call assert_equal(expected, readfile('Xtest'))
549
550  call cursor(3, 1)
551  set encoding=cp866
552  .w! ++enc=utf-8 Xtest
553  .w ++enc=cp1251 >> Xtest
554  .w ++enc=cp866 >> Xtest
555  .w! ++enc=cp866 Xcp866
556  let expected =<< trim END
557    3 cp866 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
558    3 cp866 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
559    3 cp866 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
560  END
561  call assert_equal(expected, readfile('Xtest'))
562
563  " read three 'fileencoding's with utf-8 'encoding'
564  set encoding=utf-8 fencs=utf-8,cp1251
565  e Xutf8
566  .w! ++enc=utf-8 Xtest
567  e Xcp1251
568  .w ++enc=utf-8 >> Xtest
569  set fencs=utf-8,cp866
570  e Xcp866
571  .w ++enc=utf-8 >> Xtest
572  let expected =<< trim END
573    1 utf-8 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
574    2 cp1251 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
575    3 cp866 text: Для Vim version 6.2.  Последнее изменение: 1970 Jan 01
576  END
577  call assert_equal(expected, readfile('Xtest'))
578
579  " read three 'fileencoding's with cp1251 'encoding'
580  set encoding=utf-8 fencs=utf-8,cp1251
581  e Xutf8
582  .w! ++enc=cp1251 Xtest
583  e Xcp1251
584  .w ++enc=cp1251 >> Xtest
585  set fencs=utf-8,cp866
586  e Xcp866
587  .w ++enc=cp1251 >> Xtest
588  let expected =<< trim END
589    1 utf-8 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
590    2 cp1251 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
591    3 cp866 text: ��� Vim version 6.2.  ��������� ���������: 1970 Jan 01
592  END
593  call assert_equal(expected, readfile('Xtest'))
594
595  " read three 'fileencoding's with cp866 'encoding'
596  set encoding=cp866 fencs=utf-8,cp1251
597  e Xutf8
598  .w! ++enc=cp866 Xtest
599  e Xcp1251
600  .w ++enc=cp866 >> Xtest
601  set fencs=utf-8,cp866
602  e Xcp866
603  .w ++enc=cp866 >> Xtest
604  let expected =<< trim END
605    1 utf-8 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
606    2 cp1251 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
607    3 cp866 text: ��� Vim version 6.2.  ��᫥���� ���������: 1970 Jan 01
608  END
609  call assert_equal(expected, readfile('Xtest'))
610
611  call delete('Xfile')
612  call delete('Xtest')
613  call delete('Xutf8')
614  call delete('Xcp1251')
615  call delete('Xcp866')
616  let &encoding = save_encoding
617  let &fileencodings = save_fileencodings
618  %bw!
619endfunc
620
621" Test for writing and reading a file starting with a BOM.
622" Byte Order Mark (BOM) character for various encodings is below:
623"     UTF-8      : EF BB BF
624"     UTF-16 (BE): FE FF
625"     UTF-16 (LE): FF FE
626"     UTF-32 (BE): 00 00 FE FF
627"     UTF-32 (LE): FF FE 00 00
628func Test_readwrite_file_with_bom()
629  let utf8_bom = "\xEF\xBB\xBF"
630  let utf16be_bom = "\xFE\xFF"
631  let utf16le_bom = "\xFF\xFE"
632  let utf32be_bom = "\n\n\xFE\xFF"
633  let utf32le_bom = "\xFF\xFE\n\n"
634  let save_fileencoding = &fileencoding
635  set cpoptions+=S
636
637  " Check that editing a latin1 file doesn't see a BOM
638  call writefile(["\xFE\xFElatin-1"], 'Xtest1')
639  edit Xtest1
640  call assert_equal('latin1', &fileencoding)
641  call assert_equal(0, &bomb)
642  set fenc=latin1
643  write Xfile2
644  call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xfile2', 'b'))
645  set bomb fenc=latin1
646  write Xtest3
647  call assert_equal(["\xFE\xFElatin-1", ''], readfile('Xtest3', 'b'))
648  set bomb&
649
650  " Check utf-8 BOM
651  %bw!
652  call writefile([utf8_bom .. "utf-8"], 'Xtest1')
653  edit! Xtest1
654  call assert_equal('utf-8', &fileencoding)
655  call assert_equal(1, &bomb)
656  call assert_equal('utf-8', getline(1))
657  set fenc=latin1
658  write! Xfile2
659  call assert_equal(['utf-8', ''], readfile('Xfile2', 'b'))
660  set fenc=utf-8
661  w! Xtest3
662  call assert_equal([utf8_bom .. "utf-8", ''], readfile('Xtest3', 'b'))
663
664  " Check utf-8 with an error (will fall back to latin-1)
665  %bw!
666  call writefile([utf8_bom .. "utf-8\x80err"], 'Xtest1')
667  edit! Xtest1
668  call assert_equal('latin1', &fileencoding)
669  call assert_equal(0, &bomb)
670  call assert_equal("\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", getline(1))
671  set fenc=latin1
672  write! Xfile2
673  call assert_equal([utf8_bom .. "utf-8\x80err", ''], readfile('Xfile2', 'b'))
674  set fenc=utf-8
675  w! Xtest3
676  call assert_equal(["\xC3\xAF\xC2\xBB\xC2\xBFutf-8\xC2\x80err", ''],
677        \ readfile('Xtest3', 'b'))
678
679  " Check ucs-2 BOM
680  %bw!
681  call writefile([utf16be_bom .. "\nu\nc\ns\n-\n2\n"], 'Xtest1')
682  edit! Xtest1
683  call assert_equal('utf-16', &fileencoding)
684  call assert_equal(1, &bomb)
685  call assert_equal('ucs-2', getline(1))
686  set fenc=latin1
687  write! Xfile2
688  call assert_equal(["ucs-2", ''], readfile('Xfile2', 'b'))
689  set fenc=ucs-2
690  w! Xtest3
691  call assert_equal([utf16be_bom .. "\nu\nc\ns\n-\n2\n", ''],
692        \ readfile('Xtest3', 'b'))
693
694  " Check ucs-2le BOM
695  %bw!
696  call writefile([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n"], 'Xtest1')
697  " Need to add a NUL byte after the NL byte
698  call writefile(0z00, 'Xtest1', 'a')
699  edit! Xtest1
700  call assert_equal('utf-16le', &fileencoding)
701  call assert_equal(1, &bomb)
702  call assert_equal('ucs-2le', getline(1))
703  set fenc=latin1
704  write! Xfile2
705  call assert_equal(["ucs-2le", ''], readfile('Xfile2', 'b'))
706  set fenc=ucs-2le
707  w! Xtest3
708  call assert_equal([utf16le_bom .. "u\nc\ns\n-\n2\nl\ne\n", "\n"],
709        \ readfile('Xtest3', 'b'))
710
711  " Check ucs-4 BOM
712  %bw!
713  call writefile([utf32be_bom .. "\n\n\nu\n\n\nc\n\n\ns\n\n\n-\n\n\n4\n\n\n"], 'Xtest1')
714  edit! Xtest1
715  call assert_equal('ucs-4', &fileencoding)
716  call assert_equal(1, &bomb)
717  call assert_equal('ucs-4', getline(1))
718  set fenc=latin1
719  write! Xfile2
720  call assert_equal(["ucs-4", ''], readfile('Xfile2', 'b'))
721  set fenc=ucs-4
722  w! Xtest3
723  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'))
724
725  " Check ucs-4le BOM
726  %bw!
727  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')
728  " Need to add three NUL bytes after the NL byte
729  call writefile(0z000000, 'Xtest1', 'a')
730  edit! Xtest1
731  call assert_equal('ucs-4le', &fileencoding)
732  call assert_equal(1, &bomb)
733  call assert_equal('ucs-4le', getline(1))
734  set fenc=latin1
735  write! Xfile2
736  call assert_equal(["ucs-4le", ''], readfile('Xfile2', 'b'))
737  set fenc=ucs-4le
738  w! Xtest3
739  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'))
740
741  set cpoptions-=S
742  let &fileencoding = save_fileencoding
743  call delete('Xtest1')
744  call delete('Xfile2')
745  call delete('Xtest3')
746  %bw!
747endfunc
748
749func Test_read_write_bin()
750  " write file missing EOL
751  call writefile(['noeol'], "XNoEolSetEol", 'bS')
752  call assert_equal(0z6E6F656F6C, readfile('XNoEolSetEol', 'B'))
753
754  " when file is read 'eol' is off
755  set nofixeol
756  e! ++ff=unix XNoEolSetEol
757  call assert_equal(0, &eol)
758
759  " writing with 'eol' set adds the newline
760  setlocal eol
761  w
762  call assert_equal(0z6E6F656F6C0A, readfile('XNoEolSetEol', 'B'))
763
764  call delete('XNoEolSetEol')
765  set ff& fixeol&
766  bwipe! XNoEolSetEol
767endfunc
768
769" Test for the 'backupcopy' option when writing files
770func Test_backupcopy()
771  CheckUnix
772  set backupskip=
773  " With the default 'backupcopy' setting, saving a symbolic link file
774  " should not break the link.
775  set backupcopy&
776  call writefile(['1111'], 'Xfile1')
777  silent !ln -s Xfile1 Xfile2
778  new Xfile2
779  call setline(1, ['2222'])
780  write
781  close
782  call assert_equal(['2222'], readfile('Xfile1'))
783  call assert_equal('Xfile1', resolve('Xfile2'))
784  call assert_equal('link', getftype('Xfile2'))
785  call delete('Xfile1')
786  call delete('Xfile2')
787
788  " With the 'backupcopy' set to 'breaksymlink', saving a symbolic link file
789  " should break the link.
790  set backupcopy=yes,breaksymlink
791  call writefile(['1111'], 'Xfile1')
792  silent !ln -s Xfile1 Xfile2
793  new Xfile2
794  call setline(1, ['2222'])
795  write
796  close
797  call assert_equal(['1111'], readfile('Xfile1'))
798  call assert_equal(['2222'], readfile('Xfile2'))
799  call assert_equal('Xfile2', resolve('Xfile2'))
800  call assert_equal('file', getftype('Xfile2'))
801  call delete('Xfile1')
802  call delete('Xfile2')
803  set backupcopy&
804
805  " With the default 'backupcopy' setting, saving a hard link file
806  " should not break the link.
807  set backupcopy&
808  call writefile(['1111'], 'Xfile1')
809  silent !ln Xfile1 Xfile2
810  new Xfile2
811  call setline(1, ['2222'])
812  write
813  close
814  call assert_equal(['2222'], readfile('Xfile1'))
815  call delete('Xfile1')
816  call delete('Xfile2')
817
818  " With the 'backupcopy' set to 'breaksymlink', saving a hard link file
819  " should break the link.
820  set backupcopy=yes,breakhardlink
821  call writefile(['1111'], 'Xfile1')
822  silent !ln Xfile1 Xfile2
823  new Xfile2
824  call setline(1, ['2222'])
825  write
826  call assert_equal(['1111'], readfile('Xfile1'))
827  call assert_equal(['2222'], readfile('Xfile2'))
828  call delete('Xfile1')
829  call delete('Xfile2')
830
831  " If a backup file is already present, then a slightly modified filename
832  " should be used as the backup file. Try with 'backupcopy' set to 'yes' and
833  " 'no'.
834  %bw
835  call writefile(['aaaa'], 'Xfile')
836  call writefile(['bbbb'], 'Xfile.bak')
837  set backupcopy=yes backupext=.bak
838  new Xfile
839  call setline(1, ['cccc'])
840  write
841  close
842  call assert_equal(['cccc'], readfile('Xfile'))
843  call assert_equal(['bbbb'], readfile('Xfile.bak'))
844  set backupcopy=no backupext=.bak
845  new Xfile
846  call setline(1, ['dddd'])
847  write
848  close
849  call assert_equal(['dddd'], readfile('Xfile'))
850  call assert_equal(['bbbb'], readfile('Xfile.bak'))
851  call delete('Xfile')
852  call delete('Xfile.bak')
853
854  " Write to a device file (in Unix-like systems) which cannot be backed up.
855  if has('unix')
856    set writebackup backupcopy=yes nobackup
857    new
858    call setline(1, ['aaaa'])
859    let output = execute('write! /dev/null')
860    call assert_match('"/dev/null" \[Device]', output)
861    close
862    set writebackup backupcopy=no 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 backup writebackup& backupcopy&
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  endif
875
876  set backupcopy& backupskip& backupext& backup&
877endfunc
878
879" Test for writing a file with 'encoding' set to 'utf-16'
880func Test_write_utf16()
881  new
882  call setline(1, ["\U00010001"])
883  write ++enc=utf-16 Xfile
884  bw!
885  call assert_equal(0zD800DC01, readfile('Xfile', 'B')[0:3])
886  call delete('Xfile')
887endfunc
888
889" Test for trying to save a backup file when the backup file is a symbolic
890" link to the original file. The backup file should not be modified.
891func Test_write_backup_symlink()
892  CheckUnix
893  call writefile(['1111'], 'Xfile')
894  silent !ln -s Xfile Xfile.bak
895
896  new Xfile
897  set backup backupcopy=yes backupext=.bak
898  write
899  call assert_equal('link', getftype('Xfile.bak'))
900  call assert_equal('Xfile', resolve('Xfile.bak'))
901  set backup& backupcopy& backupext&
902  close
903
904  call delete('Xfile')
905  call delete('Xfile.bak')
906endfunc
907
908" Test for ':write ++bin' and ':write ++nobin'
909func Test_write_binary_file()
910  " create a file without an eol/eof character
911  call writefile(0z616161, 'Xfile1', 'b')
912  new Xfile1
913  write ++bin Xfile2
914  write ++nobin Xfile3
915  call assert_equal(0z616161, readblob('Xfile2'))
916  if has('win32')
917    call assert_equal(0z6161610D.0A, readblob('Xfile3'))
918  else
919    call assert_equal(0z6161610A, readblob('Xfile3'))
920  endif
921  call delete('Xfile1')
922  call delete('Xfile2')
923  call delete('Xfile3')
924endfunc
925
926" Check that buffer is written before triggering QuitPre
927func Test_wq_quitpre_autocommand()
928  edit Xsomefile
929  call setline(1, 'hello')
930  split
931  let g:seq = []
932  augroup Testing
933    au QuitPre * call add(g:seq, 'QuitPre - ' .. (&modified ? 'modified' : 'not modified'))
934    au BufWritePost * call add(g:seq, 'written')
935  augroup END
936  wq
937  call assert_equal(['written', 'QuitPre - not modified'], g:seq)
938
939  augroup Testing
940    au!
941  augroup END
942  bwipe!
943  unlet g:seq
944  call delete('Xsomefile')
945endfunc
946
947" vim: shiftwidth=2 sts=2 expandtab
948