blob: e94071fd7defb9f7e99c14d1909c234a84e1df93 [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')
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
Bram Moolenaar4f5776c2020-02-12 22:15:19 +0100242 call assert_fails('w > Xtest', 'E494:')
Bram Moolenaarbc2b71d2020-02-17 21:33:30 +0100243
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100244 " 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')
Bram Moolenaar99fa7212020-04-26 15:59:55 +0200271
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:')
Bram Moolenaar494e9062020-05-31 21:28:02 +0200277
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:')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200282
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
Bram Moolenaar50157ef2021-05-15 23:21:05 +0200288 call assert_fails('write', 'E503: ')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200289 call assert_fails('write!', 'E503: ')
290 close!
291 endif
Bram Moolenaar494e9062020-05-31 21:28:02 +0200292endfunc
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})
Bram Moolenaar733d2592020-08-20 18:59:06 +0200303 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200304 call term_sendkeys(buf, ":set noswapfile\<CR>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200305 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200306
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>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200321 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200322 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>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200326 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200327 call assert_equal(new_ftime, getftime('Xfile'))
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 term_sendkeys(buf, "y\<CR>")
Bram Moolenaar733d2592020-08-20 18:59:06 +0200331 call TermWait(buf)
Bram Moolenaar494e9062020-05-31 21:28:02 +0200332 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
Bram Moolenaare2e40752020-09-04 21:18:46 +0200345 call assert_fails('lockmarks write', ['E32:', 'E203:'])
Bram Moolenaar494e9062020-05-31 21:28:02 +0200346 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()
Bram Moolenaar494e9062020-05-31 21:28:02 +0200406 call writefile([], 'Xfile')
407 call setfperm('Xfile', "r--------")
408 edit Xfile
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200409 set noreadonly backupskip=
Bram Moolenaar494e9062020-05-31 21:28:02 +0200410 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
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200415 call setline(1, ['line1'])
416 write!
417 call assert_equal(['line1'], readfile('Xfile'))
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200418
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
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200430 set backupskip&
Bram Moolenaar494e9062020-05-31 21:28:02 +0200431 call delete('Xfile')
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200432 %bw!
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100433endfunc
434
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200435" Test for 'patchmode'
436func Test_patchmode()
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200437 call writefile(['one'], 'Xfile')
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200438 set patchmode=.orig nobackup backupskip= writebackup
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200439 new Xfile
440 call setline(1, 'two')
441 " first write should create the .orig file
442 write
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200443 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'))
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200448
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
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200461 set patchmode& backup& backupskip& writebackup&
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200462 call delete('Xfile')
463 call delete('Xfile.orig')
464endfunc
465
466" Test for writing to a file in a readonly directory
Bram Moolenaarf9a65502021-03-05 20:47:44 +0100467" NOTE: if you run tests as root this will fail. Don't run tests as root!
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200468func Test_write_readonly_dir()
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200469 " On MS-Windows, modifying files in a read-only directory is allowed.
470 CheckUnix
Bram Moolenaar17709e22021-03-19 14:38:12 +0100471 " Root can do it too.
472 CheckNotRoot
473
Yegappan Lakshmanan46aa6f92021-05-19 17:15:04 +0200474 call mkdir('Xdir/')
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200475 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
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200483 set backupdir=./Xdir backupskip=
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200484 set patchmode=.orig
485 call assert_fails('write', 'E509:')
486 call setfperm('Xdir', 'rwxr--r--')
487 call delete('Xdir', 'rf')
Bram Moolenaarb86abad2020-08-01 16:08:19 +0200488 set backupdir& backupskip& patchmode&
Bram Moolenaar1de5f7c2020-06-11 19:22:43 +0200489endfunc
490
Bram Moolenaarb340bae2020-06-15 19:51:56 +0200491" 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
Bram Moolenaar622b3562020-07-27 20:02:41 +0200499" 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
Bram Moolenaarb61ef012020-07-29 16:08:21 +0200613" 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')
Bram Moolenaar733d2592020-08-20 18:59:06 +0200736 call delete('Xfile2')
Bram Moolenaarb61ef012020-07-29 16:08:21 +0200737 call delete('Xtest3')
738 %bw!
739endfunc
740
Bram Moolenaarb3c8b1d2020-12-23 18:54:57 +0100741func 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
Bram Moolenaar16204962020-12-23 22:40:11 +0100747 set nofixeol
748 e! ++ff=unix XNoEolSetEol
Bram Moolenaarb3c8b1d2020-12-23 18:54:57 +0100749 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')
Yegappan Lakshmanan46aa6f92021-05-19 17:15:04 +0200757 set ff& fixeol&
Bram Moolenaarbd318552020-12-23 20:55:15 +0100758 bwipe! XNoEolSetEol
Bram Moolenaarb3c8b1d2020-12-23 18:54:57 +0100759endfunc
760
Yegappan Lakshmanan36f96a52021-05-13 18:33:16 +0200761" 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
Yegappan Lakshmanan46aa6f92021-05-19 17:15:04 +0200900" Test for ':write ++bin' and ':write ++nobin'
901func Test_write_binary_file()
902 " create a file without an eol/eof character
903 call writefile(0z616161, 'Xfile1', 'b')
904 new Xfile1
905 write ++bin Xfile2
906 write ++nobin Xfile3
907 call assert_equal(0z616161, readblob('Xfile2'))
908 if has('win32')
909 call assert_equal(0z6161610D.0A, readblob('Xfile3'))
910 else
911 call assert_equal(0z6161610A, readblob('Xfile3'))
912 endif
913 call delete('Xfile1')
914 call delete('Xfile2')
915 call delete('Xfile3')
916endfunc
917
Bram Moolenaar1174b012021-05-29 14:30:43 +0200918" Check that buffer is written before triggering QuitPre
919func Test_wq_quitpre_autocommand()
920 edit Xsomefile
921 call setline(1, 'hello')
922 split
923 let g:seq = []
924 augroup Testing
925 au QuitPre * call add(g:seq, 'QuitPre - ' .. (&modified ? 'modified' : 'not modified'))
926 au BufWritePost * call add(g:seq, 'written')
927 augroup END
928 wq
929 call assert_equal(['written', 'QuitPre - not modified'], g:seq)
930
931 augroup Testing
932 au!
933 augroup END
934 bwipe!
935 unlet g:seq
936 call delete('Xsomefile')
937endfunc
938
Bram Moolenaar5d98dc22020-01-29 21:57:34 +0100939" vim: shiftwidth=2 sts=2 expandtab