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