test_writefile.vim 28 KB

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