blob: a8204ef02d12e1271f1cabc93bca59651a7d46b4 [file] [log] [blame]
Bram Moolenaarb40c2572019-10-19 21:01:05 +02001" Tests for the writefile() function and some :write commands.
Bram Moolenaar19a16692016-09-01 22:19:47 +02002
Bram Moolenaarea3db912020-02-02 15:32:13 +01003source check.vim
Bram Moolenaar494e9062020-05-31 21:28:02 +02004source term_util.vim
Bram Moolenaarea3db912020-02-02 15:32:13 +01005
Bram Moolenaar8cf91282017-06-13 19:38:37 +02006func Test_writefile()
Bram Moolenaar19a16692016-09-01 22:19:47 +02007 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)
Bram Moolenaar18a2b872020-03-19 13:08:45 +010020
21 call assert_fails('call writefile("text", "Xfile")', 'E475: Invalid argument: writefile() first argument must be a List or a Blob')
Bram Moolenaar8cf91282017-06-13 19:38:37 +020022endfunc
23
Bram Moolenaarb40c2572019-10-19 21:01:05 +020024func Test_writefile_ignore_regexp_error()
25 write Xt[z-a]est.txt
26 call delete('Xt[z-a]est.txt')
27endfunc
28
Bram Moolenaar8cf91282017-06-13 19:38:37 +020029func 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
Bram Moolenaare6bf6552017-06-27 22:11:51 +020044
45func Test_writefile_fails_conversion()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020046 CheckFeature iconv
47 if has('sun')
48 throw 'Skipped: does not work on SunOS'
Bram Moolenaare6bf6552017-06-27 22:11:51 +020049 endif
Bram Moolenaarcf0bfd92019-05-18 18:52:04 +020050 " Without a backup file the write won't happen if there is a conversion
51 " error.
Bram Moolenaarc28cb5b2019-05-31 20:42:09 +020052 set nobackup nowritebackup backupdir=. backupskip=
Bram Moolenaare6bf6552017-06-27 22:11:51 +020053 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"])
Bram Moolenaarcf0bfd92019-05-18 18:52:04 +020058 call assert_fails('write ++enc=cp932', 'E513:')
Bram Moolenaare6bf6552017-06-27 22:11:51 +020059 call assert_equal(contents, readfile('Xfile'))
60
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +020061 " 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
Bram Moolenaare6bf6552017-06-27 22:11:51 +020082 call delete('Xfile')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +020083 call delete('Xfile' .. &backupext)
Bram Moolenaare6bf6552017-06-27 22:11:51 +020084 bwipe!
Bram Moolenaarc28cb5b2019-05-31 20:42:09 +020085 set backup& writebackup& backupdir&vim backupskip&vim
Bram Moolenaare6bf6552017-06-27 22:11:51 +020086endfunc
Bram Moolenaar2c33d7b2017-10-14 16:06:20 +020087
Bram Moolenaarcf0bfd92019-05-18 18:52:04 +020088func Test_writefile_fails_conversion2()
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020089 CheckFeature iconv
90 if has('sun')
91 throw 'Skipped: does not work on SunOS'
Bram Moolenaarcf0bfd92019-05-18 18:52:04 +020092 endif
93 " With a backup file the write happens even if there is a conversion error,
94 " but then the backup file must remain
Bram Moolenaarc28cb5b2019-05-31 20:42:09 +020095 set nobackup writebackup backupdir=. backupskip=
Bram Moolenaarcf0bfd92019-05-18 18:52:04 +020096 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!
Bram Moolenaarc28cb5b2019-05-31 20:42:09 +0200108 set backup& writebackup& backupdir&vim backupskip&vim
Bram Moolenaarcf0bfd92019-05-18 18:52:04 +0200109endfunc
110
Bram Moolenaar2c33d7b2017-10-14 16:06:20 +0200111func 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
Bram Moolenaar7567d0b2017-11-16 23:04:15 +0100154
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
Bram Moolenaar83799a72017-11-25 17:24:09 +0100161
162func Test_writefile_sync_dev_stdout()
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200163 CheckUnix
Bram Moolenaar9980b372018-04-21 20:12:35 +0200164 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
Bram Moolenaar83799a72017-11-25 17:24:09 +0100170endfunc
Bram Moolenaar8c9e7b02018-08-30 13:07:17 +0200171
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
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100209
210" Test for ':w !<cmd>' to pipe lines from the current buffer to an external
211" command.
212func Test_write_pipe_to_cmd()
Bram Moolenaarea3db912020-02-02 15:32:13 +0100213 CheckUnix
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100214 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')
Dominique Pellebd9e7962021-08-09 21:04:44 +0200233
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')
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100241endfunc
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
Bram Moolenaar4f5776c2020-02-12 22:15:19 +0100250 call assert_fails('w > Xtest', 'E494:')
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +0100251
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100252 " 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')
Bram Moolenaar99fa7212020-04-26 15:59:55 +0200279
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:')
Bram Moolenaar494e9062020-05-31 21:28:02 +0200285
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:')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200290
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
Bram Moolenaar50157ef2021-05-15 23:21:05 +0200296 call assert_fails('write', 'E503: ')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200297 call assert_fails('write!', 'E503: ')
298 close!
299 endif
Bram Moolenaar494e9062020-05-31 21:28:02 +0200300endfunc
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})
Bram Moolenaar733d2592020-08-20 18:59:06 +0200311 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200312 call term_sendkeys(buf, ":set noswapfile\<CR>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200313 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200314
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>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200329 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200330 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>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200334 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200335 call assert_equal(new_ftime, getftime('Xfile'))
336 call term_sendkeys(buf, ":w\<CR>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200337 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200338 call term_sendkeys(buf, "y\<CR>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200339 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200340 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
Bram Moolenaare2e40752020-09-04 21:18:46 +0200353 call assert_fails('lockmarks write', ['E32:', 'E203:'])
Bram Moolenaar494e9062020-05-31 21:28:02 +0200354 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()
Bram Moolenaar494e9062020-05-31 21:28:02 +0200414 call writefile([], 'Xfile')
415 call setfperm('Xfile', "r--------")
416 edit Xfile
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200417 set noreadonly backupskip=
Bram Moolenaar494e9062020-05-31 21:28:02 +0200418 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
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200423 call setline(1, ['line1'])
424 write!
425 call assert_equal(['line1'], readfile('Xfile'))
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200426
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
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200438 set backupskip&
Bram Moolenaar494e9062020-05-31 21:28:02 +0200439 call delete('Xfile')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200440 %bw!
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100441endfunc
442
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200443" Test for 'patchmode'
444func Test_patchmode()
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200445 call writefile(['one'], 'Xfile')
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200446 set patchmode=.orig nobackup backupskip= writebackup
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200447 new Xfile
448 call setline(1, 'two')
449 " first write should create the .orig file
450 write
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200451 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'))
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200456
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
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200469 set patchmode& backup& backupskip& writebackup&
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200470 call delete('Xfile')
471 call delete('Xfile.orig')
472endfunc
473
474" Test for writing to a file in a readonly directory
Bram Moolenaarf9a65502021-03-05 20:47:44 +0100475" NOTE: if you run tests as root this will fail. Don't run tests as root!
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200476func Test_write_readonly_dir()
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200477 " On MS-Windows, modifying files in a read-only directory is allowed.
478 CheckUnix
Bram Moolenaar17709e22021-03-19 14:38:12 +0100479 " Root can do it too.
480 CheckNotRoot
481
Yegappan Lakshmanan46aa6f92021-05-19 17:15:04 +0200482 call mkdir('Xdir/')
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200483 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
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200491 set backupdir=./Xdir backupskip=
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200492 set patchmode=.orig
493 call assert_fails('write', 'E509:')
494 call setfperm('Xdir', 'rwxr--r--')
495 call delete('Xdir', 'rf')
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200496 set backupdir& backupskip& patchmode&
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200497endfunc
498
Bram Moolenaarb340bae2020-06-15 19:51:56 +0200499" 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
Bram Moolenaar622b3562020-07-27 20:02:41 +0200507" 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
K.Takataf883d902021-05-30 18:04:19 +0200512 set encoding=latin1 fileencodings&
Bram Moolenaar622b3562020-07-27 20:02:41 +0200513 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
Bram Moolenaarb61ef012020-07-29 16:08:21 +0200621" 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')
Bram Moolenaar733d2592020-08-20 18:59:06 +0200744 call delete('Xfile2')
Bram Moolenaarb61ef012020-07-29 16:08:21 +0200745 call delete('Xtest3')
746 %bw!
747endfunc
748
Bram Moolenaarb3c8b1d2020-12-23 18:54:57 +0100749func 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
Bram Moolenaar16204962020-12-23 22:40:11 +0100755 set nofixeol
756 e! ++ff=unix XNoEolSetEol
Bram Moolenaarb3c8b1d2020-12-23 18:54:57 +0100757 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')
Yegappan Lakshmanan46aa6f92021-05-19 17:15:04 +0200765 set ff& fixeol&
Bram Moolenaarbd318552020-12-23 20:55:15 +0100766 bwipe! XNoEolSetEol
Bram Moolenaarb3c8b1d2020-12-23 18:54:57 +0100767endfunc
768
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200769" 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
Yegappan Lakshmanan46aa6f92021-05-19 17:15:04 +0200908" 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
Bram Moolenaar1174b012021-05-29 14:30:43 +0200926" 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
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100947" vim: shiftwidth=2 sts=2 expandtab