xref: /vim-8.2.3635/src/testdir/test_swap.vim (revision ea2d8d25)
1" Tests for the swap feature
2
3source check.vim
4source shared.vim
5source term_util.vim
6
7func s:swapname()
8  return trim(execute('swapname'))
9endfunc
10
11" Tests for 'directory' option.
12func Test_swap_directory()
13  if !has("unix")
14    return
15  endif
16  let content = ['start of testfile',
17	      \ 'line 2 Abcdefghij',
18	      \ 'line 3 Abcdefghij',
19	      \ 'end of testfile']
20  call writefile(content, 'Xtest1')
21
22  "  '.', swap file in the same directory as file
23  set dir=.,~
24
25  " Verify that the swap file doesn't exist in the current directory
26  call assert_equal([], glob(".Xtest1*.swp", 1, 1, 1))
27  edit Xtest1
28  let swfname = s:swapname()
29  call assert_equal([swfname], glob(swfname, 1, 1, 1))
30
31  " './dir', swap file in a directory relative to the file
32  set dir=./Xtest2,.,~
33
34  call mkdir("Xtest2")
35  edit Xtest1
36  call assert_equal([], glob(swfname, 1, 1, 1))
37  let swfname = "Xtest2/Xtest1.swp"
38  call assert_equal(swfname, s:swapname())
39  call assert_equal([swfname], glob("Xtest2/*", 1, 1, 1))
40
41  " 'dir', swap file in directory relative to the current dir
42  set dir=Xtest.je,~
43
44  call mkdir("Xtest.je")
45  call writefile(content, 'Xtest2/Xtest3')
46  edit Xtest2/Xtest3
47  call assert_equal(["Xtest2/Xtest3"], glob("Xtest2/*", 1, 1, 1))
48  let swfname = "Xtest.je/Xtest3.swp"
49  call assert_equal(swfname, s:swapname())
50  call assert_equal([swfname], glob("Xtest.je/*", 1, 1, 1))
51
52  set dir&
53  call delete("Xtest1")
54  call delete("Xtest2", "rf")
55  call delete("Xtest.je", "rf")
56endfunc
57
58func Test_swap_group()
59  if !has("unix")
60    return
61  endif
62  let groups = split(system('groups'))
63  if len(groups) <= 1
64    throw 'Skipped: need at least two groups, got ' . string(groups)
65  endif
66
67  try
68    call delete('Xtest')
69    split Xtest
70    call setline(1, 'just some text')
71    wq
72    if system('ls -l Xtest') !~ ' ' . groups[0] . ' \d'
73      throw 'Skipped: test file does not have the first group'
74    else
75      silent !chmod 640 Xtest
76      call system('chgrp ' . groups[1] . ' Xtest')
77      if system('ls -l Xtest') !~ ' ' . groups[1] . ' \d'
78	throw 'Skipped: cannot set second group on test file'
79      else
80	split Xtest
81	let swapname = s:swapname()
82	call assert_match('Xtest', swapname)
83	" Group of swapfile must now match original file.
84	call assert_match(' ' . groups[1] . ' \d', system('ls -l ' . swapname))
85
86	bwipe!
87      endif
88    endif
89  finally
90    call delete('Xtest')
91  endtry
92endfunc
93
94func Test_missing_dir()
95  call mkdir('Xswapdir')
96  exe 'set directory=' . getcwd() . '/Xswapdir'
97
98  call assert_equal('', glob('foo'))
99  call assert_equal('', glob('bar'))
100  edit foo/x.txt
101  " This should not give a warning for an existing swap file.
102  split bar/x.txt
103  only
104
105  " Delete the buffer so that swap file is removed before we try to delete the
106  " directory.  That fails on MS-Windows.
107  %bdelete!
108  set directory&
109  call delete('Xswapdir', 'rf')
110endfunc
111
112func Test_swapinfo()
113  new Xswapinfo
114  call setline(1, ['one', 'two', 'three'])
115  w
116  let fname = s:swapname()
117  call assert_match('Xswapinfo', fname)
118  let info = fname->swapinfo()
119
120  let ver = printf('VIM %d.%d', v:version / 100, v:version % 100)
121  call assert_equal(ver, info.version)
122
123  call assert_match('\w', info.user)
124  " host name is truncated to 39 bytes in the swap file
125  call assert_equal(hostname()[:38], info.host)
126  call assert_match('Xswapinfo', info.fname)
127  call assert_match(0, info.dirty)
128  call assert_equal(getpid(), info.pid)
129  call assert_match('^\d*$', info.mtime)
130  if has_key(info, 'inode')
131    call assert_match('\d', info.inode)
132  endif
133  bwipe!
134  call delete(fname)
135  call delete('Xswapinfo')
136
137  let info = swapinfo('doesnotexist')
138  call assert_equal('Cannot open file', info.error)
139
140  call writefile(['burp'], 'Xnotaswapfile')
141  let info = swapinfo('Xnotaswapfile')
142  call assert_equal('Cannot read file', info.error)
143  call delete('Xnotaswapfile')
144
145  call writefile([repeat('x', 10000)], 'Xnotaswapfile')
146  let info = swapinfo('Xnotaswapfile')
147  call assert_equal('Not a swap file', info.error)
148  call delete('Xnotaswapfile')
149endfunc
150
151func Test_swapname()
152  edit Xtest1
153  let expected = s:swapname()
154  call assert_equal(expected, swapname('%'))
155
156  new Xtest2
157  let buf = bufnr('%')
158  let expected = s:swapname()
159  wincmd p
160  call assert_equal(expected, buf->swapname())
161
162  new Xtest3
163  setlocal noswapfile
164  call assert_equal('', swapname('%'))
165
166  bwipe!
167  call delete('Xtest1')
168  call delete('Xtest2')
169  call delete('Xtest3')
170endfunc
171
172func Test_swapfile_delete()
173  autocmd! SwapExists
174  function s:swap_exists()
175    let v:swapchoice = s:swap_choice
176    let s:swapname = v:swapname
177    let s:filename = expand('<afile>')
178  endfunc
179  augroup test_swapfile_delete
180    autocmd!
181    autocmd SwapExists * call s:swap_exists()
182  augroup END
183
184
185  " Create a valid swapfile by editing a file.
186  split XswapfileText
187  call setline(1, ['one', 'two', 'three'])
188  write  " file is written, not modified
189  " read the swapfile as a Blob
190  let swapfile_name = swapname('%')
191  let swapfile_bytes = readfile(swapfile_name, 'B')
192
193  " Close the file and recreate the swap file.
194  " Now editing the file will run into the process still existing
195  quit
196  call writefile(swapfile_bytes, swapfile_name)
197  let s:swap_choice = 'e'
198  let s:swapname = ''
199  split XswapfileText
200  quit
201  call assert_equal(fnamemodify(swapfile_name, ':t'), fnamemodify(s:swapname, ':t'))
202
203  " This test won't work as root because root can successfully run kill(1, 0)
204  if !IsRoot()
205    " Write the swapfile with a modified PID, now it will be automatically
206    " deleted. Process one should never be Vim.
207    let swapfile_bytes[24:27] = 0z01000000
208    call writefile(swapfile_bytes, swapfile_name)
209    let s:swapname = ''
210    split XswapfileText
211    quit
212    call assert_equal('', s:swapname)
213  endif
214
215  " Now set the modified flag, the swap file will not be deleted
216  let swapfile_bytes[28 + 80 + 899] = 0x55
217  call writefile(swapfile_bytes, swapfile_name)
218  let s:swapname = ''
219  split XswapfileText
220  quit
221  call assert_equal(fnamemodify(swapfile_name, ':t'), fnamemodify(s:swapname, ':t'))
222
223  call delete('XswapfileText')
224  call delete(swapfile_name)
225  augroup test_swapfile_delete
226    autocmd!
227  augroup END
228  augroup! test_swapfile_delete
229endfunc
230
231func Test_swap_recover()
232  autocmd! SwapExists
233  augroup test_swap_recover
234    autocmd!
235    autocmd SwapExists * let v:swapchoice = 'r'
236  augroup END
237
238
239  call mkdir('Xswap')
240  let $Xswap = 'foo'  " Check for issue #4369.
241  set dir=Xswap//
242  " Create a valid swapfile by editing a file.
243  split Xswap/text
244  call setline(1, ['one', 'two', 'three'])
245  write  " file is written, not modified
246  " read the swapfile as a Blob
247  let swapfile_name = swapname('%')
248  let swapfile_bytes = readfile(swapfile_name, 'B')
249
250  " Close the file and recreate the swap file.
251  quit
252  call writefile(swapfile_bytes, swapfile_name)
253  " Edit the file again. This triggers recovery.
254  try
255    split Xswap/text
256  catch
257    " E308 should be caught, not E305.
258    call assert_exception('E308:')  " Original file may have been changed
259  endtry
260  " The file should be recovered.
261  call assert_equal(['one', 'two', 'three'], getline(1, 3))
262  quit!
263
264  call delete('Xswap/text')
265  call delete(swapfile_name)
266  call delete('Xswap', 'd')
267  unlet $Xswap
268  set dir&
269  augroup test_swap_recover
270    autocmd!
271  augroup END
272  augroup! test_swap_recover
273endfunc
274
275func Test_swap_recover_ext()
276  autocmd! SwapExists
277  augroup test_swap_recover_ext
278    autocmd!
279    autocmd SwapExists * let v:swapchoice = 'r'
280  augroup END
281
282  " Create a valid swapfile by editing a file with a special extension.
283  split Xtest.scr
284  call setline(1, ['one', 'two', 'three'])
285  write  " file is written, not modified
286  write  " write again to make sure the swapfile is created
287  " read the swapfile as a Blob
288  let swapfile_name = swapname('%')
289  let swapfile_bytes = readfile(swapfile_name, 'B')
290
291  " Close and delete the file and recreate the swap file.
292  quit
293  call delete('Xtest.scr')
294  call writefile(swapfile_bytes, swapfile_name)
295  " Edit the file again. This triggers recovery.
296  try
297    split Xtest.scr
298  catch
299    " E308 should be caught, not E306.
300    call assert_exception('E308:')  " Original file may have been changed
301  endtry
302  " The file should be recovered.
303  call assert_equal(['one', 'two', 'three'], getline(1, 3))
304  quit!
305
306  call delete('Xtest.scr')
307  call delete(swapfile_name)
308  augroup test_swap_recover_ext
309    autocmd!
310  augroup END
311  augroup! test_swap_recover_ext
312endfunc
313
314" Test for closing a split window automatically when a swap file is detected
315" and 'Q' is selected in the confirmation prompt.
316func Test_swap_split_win()
317  autocmd! SwapExists
318  augroup test_swap_splitwin
319    autocmd!
320    autocmd SwapExists * let v:swapchoice = 'q'
321  augroup END
322
323  " Create a valid swapfile by editing a file with a special extension.
324  split Xtest.scr
325  call setline(1, ['one', 'two', 'three'])
326  write  " file is written, not modified
327  write  " write again to make sure the swapfile is created
328  " read the swapfile as a Blob
329  let swapfile_name = swapname('%')
330  let swapfile_bytes = readfile(swapfile_name, 'B')
331
332  " Close and delete the file and recreate the swap file.
333  quit
334  call delete('Xtest.scr')
335  call writefile(swapfile_bytes, swapfile_name)
336  " Split edit the file again. This should fail to open the window
337  try
338    split Xtest.scr
339  catch
340    " E308 should be caught, not E306.
341    call assert_exception('E308:')  " Original file may have been changed
342  endtry
343  call assert_equal(1, winnr('$'))
344
345  call delete('Xtest.scr')
346  call delete(swapfile_name)
347
348  augroup test_swap_splitwin
349      autocmd!
350  augroup END
351  augroup! test_swap_splitwin
352endfunc
353
354" Test for selecting 'q' in the attention prompt
355func Test_swap_prompt_splitwin()
356  CheckRunVimInTerminal
357
358  call writefile(['foo bar'], 'Xfile1')
359  edit Xfile1
360  preserve  " should help to make sure the swap file exists
361
362  let buf = RunVimInTerminal('', {'rows': 20})
363  call term_sendkeys(buf, ":set nomore\n")
364  call term_sendkeys(buf, ":set noruler\n")
365  call term_sendkeys(buf, ":split Xfile1\n")
366  call TermWait(buf)
367  call WaitForAssert({-> assert_match('^\[O\]pen Read-Only, (E)dit anyway, (R)ecover, (Q)uit, (A)bort: $', term_getline(buf, 20))})
368  call term_sendkeys(buf, "q")
369  call TermWait(buf)
370  call term_sendkeys(buf, ":\<CR>")
371  call WaitForAssert({-> assert_match('^:$', term_getline(buf, 20))})
372  call term_sendkeys(buf, ":echomsg winnr('$')\<CR>")
373  call TermWait(buf)
374  call WaitForAssert({-> assert_match('^1$', term_getline(buf, 20))})
375  call StopVimInTerminal(buf)
376  %bwipe!
377  call delete('Xfile1')
378endfunc
379
380func Test_swap_symlink()
381  if !has("unix")
382    return
383  endif
384
385  call writefile(['text'], 'Xtestfile')
386  silent !ln -s -f Xtestfile Xtestlink
387
388  set dir=.
389
390  " Test that swap file uses the name of the file when editing through a
391  " symbolic link (so that editing the file twice is detected)
392  edit Xtestlink
393  call assert_match('Xtestfile\.swp$', s:swapname())
394  bwipe!
395
396  call mkdir('Xswapdir')
397  exe 'set dir=' . getcwd() . '/Xswapdir//'
398
399  " Check that this also works when 'directory' ends with '//'
400  edit Xtestlink
401  call assert_match('Xtestfile\.swp$', s:swapname())
402  bwipe!
403
404  set dir&
405  call delete('Xtestfile')
406  call delete('Xtestlink')
407  call delete('Xswapdir', 'rf')
408endfunc
409
410" vim: shiftwidth=2 sts=2 expandtab
411