blob: 7e96622d1a5619700dd50c1f0ebaa4caa19fea19 [file] [log] [blame]
Bram Moolenaarc525e3a2017-02-18 16:59:02 +01001" Test :recover
2
Bram Moolenaarf52f0602021-03-10 21:26:37 +01003source check.vim
4
Bram Moolenaarc525e3a2017-02-18 16:59:02 +01005func Test_recover_root_dir()
6 " This used to access invalid memory.
7 split Xtest
8 set dir=/
9 call assert_fails('recover', 'E305:')
10 close!
11
Bram Moolenaar2a0b06d2017-05-18 16:23:43 +020012 if has('win32') || filewritable('/') == 2
Bram Moolenaar80345202017-02-18 22:43:19 +010013 " can write in / directory on MS-Windows
14 set dir=/notexist/
15 endif
Bram Moolenaarc525e3a2017-02-18 16:59:02 +010016 call assert_fails('split Xtest', 'E303:')
Bram Moolenaar00e192b2019-10-19 17:01:28 +020017
18 " No error with empty 'directory' setting.
19 set directory=
20 split XtestOK
21 close!
22
Bram Moolenaarc525e3a2017-02-18 16:59:02 +010023 set dir&
24endfunc
25
Bram Moolenaarf52f0602021-03-10 21:26:37 +010026" Make a copy of the current swap file to "Xswap".
27" Return the name of the swap file.
28func CopySwapfile()
29 preserve
30 " get the name of the swap file
31 let swname = split(execute("swapname"))[0]
32 let swname = substitute(swname, '[[:blank:][:cntrl:]]*\(.\{-}\)[[:blank:][:cntrl:]]*$', '\1', '')
33 " make a copy of the swap file in Xswap
34 set binary
35 exe 'sp ' . swname
36 w! Xswap
37 set nobinary
38 return swname
39endfunc
40
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +020041" Inserts 10000 lines with text to fill the swap file with two levels of pointer
42" blocks. Then recovers from the swap file and checks all text is restored.
43"
44" We need about 10000 lines of 100 characters to get two levels of pointer
45" blocks.
46func Test_swap_file()
Bram Moolenaar67418d92017-10-15 22:07:39 +020047 set fileformat=unix undolevels=-1
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +020048 edit! Xtest
49 let text = "\tabcdefghijklmnoparstuvwxyz0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnoparstuvwxyz0123456789"
50 let i = 1
51 let linecount = 10000
52 while i <= linecount
53 call append(i - 1, i . text)
54 let i += 1
55 endwhile
56 $delete
Bram Moolenaarf52f0602021-03-10 21:26:37 +010057
58 let swname = CopySwapfile()
59
Bram Moolenaar4a6fcf82017-10-12 21:29:22 +020060 new
61 only!
62 bwipe! Xtest
63 call rename('Xswap', swname)
64 recover Xtest
65 call delete(swname)
66 let linedollar = line('$')
67 call assert_equal(linecount, linedollar)
68 if linedollar < linecount
69 let linecount = linedollar
70 endif
71 let i = 1
72 while i <= linecount
73 call assert_equal(i . text, getline(i))
74 let i += 1
75 endwhile
76
77 set undolevels&
78 enew! | only
79endfunc
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +020080
Bram Moolenaarf52f0602021-03-10 21:26:37 +010081func Test_nocatch_process_still_running()
Bram Moolenaar6635ae12021-03-10 21:46:39 +010082 " sysinfo.uptime probably only works on Linux
Bram Moolenaar776b9542021-03-10 22:27:48 +010083 if !has('linux')
84 let g:skipped_reason = 'only works on Linux'
85 return
86 endif
Bram Moolenaar6635ae12021-03-10 21:46:39 +010087 " the GUI dialog can't be handled
Bram Moolenaar776b9542021-03-10 22:27:48 +010088 if has('gui_running')
89 let g:skipped_reason = 'only works in the terminal'
90 return
91 endif
Bram Moolenaarf52f0602021-03-10 21:26:37 +010092
93 " don't intercept existing swap file here
94 au! SwapExists
95
96 " Edit a file and grab its swapfile.
97 edit Xswaptest
98 call setline(1, ['a', 'b', 'c'])
99 let swname = CopySwapfile()
100
101 " Forget we edited this file
102 new
103 only!
104 bwipe! Xswaptest
105
106 call rename('Xswap', swname)
107 call feedkeys('e', 'tL')
108 redir => editOutput
109 edit Xswaptest
110 redir END
111 call assert_match('E325: ATTENTION', editOutput)
112 call assert_match('file name: .*Xswaptest', editOutput)
113 call assert_match('process ID: \d* (STILL RUNNING)', editOutput)
114
115 " Forget we edited this file
116 new
117 only!
118 bwipe! Xswaptest
119
120 " pretend we rebooted
121 call test_override("uptime", 0)
122 sleep 1
123
124 call rename('Xswap', swname)
125 call feedkeys('e', 'tL')
126 redir => editOutput
127 edit Xswaptest
128 redir END
129 call assert_match('E325: ATTENTION', editOutput)
130 call assert_notmatch('(STILL RUNNING)', editOutput)
131
132 call test_override("ALL", 0)
133 call delete(swname)
134endfunc
135
Yegappan Lakshmanan59b26232021-06-05 20:59:22 +0200136" Test for :recover with multiple swap files
137func Test_recover_multiple_swap_files()
138 CheckUnix
139 new Xfile1
140 call setline(1, ['a', 'b', 'c'])
141 preserve
Yegappan Lakshmanan99285552021-06-06 17:12:46 +0200142 let b = readblob(swapname(''))
Yegappan Lakshmanan59b26232021-06-05 20:59:22 +0200143 call writefile(b, '.Xfile1.swm')
144 call writefile(b, '.Xfile1.swn')
145 call writefile(b, '.Xfile1.swo')
146 %bw!
147 call feedkeys(":recover Xfile1\<CR>3\<CR>q", 'xt')
148 call assert_equal(['a', 'b', 'c'], getline(1, '$'))
149
150 call delete('.Xfile1.swm')
151 call delete('.Xfile1.swn')
152 call delete('.Xfile1.swo')
153endfunc
154
155" Test for :recover using an empty swap file
156func Test_recover_empty_swap_file()
157 CheckUnix
158 call writefile([], '.Xfile1.swp')
159 let msg = execute('recover Xfile1')
160 call assert_match('Unable to read block 0 from .Xfile1.swp', msg)
161 call assert_equal('Xfile1', @%)
162 bw!
163 " :recover from an empty buffer
164 call assert_fails('recover', 'E305:')
165 call delete('.Xfile1.swp')
166endfunc
167
168" Test for :recover using a corrupted swap file
169func Test_recover_corrupted_swap_file()
170 CheckUnix
Yegappan Lakshmanan99285552021-06-06 17:12:46 +0200171
Yegappan Lakshmanan59b26232021-06-05 20:59:22 +0200172 " recover using a partial swap file
173 call writefile(0z1234, '.Xfile1.swp')
174 call assert_fails('recover Xfile1', 'E295:')
175 bw!
176
177 " recover using invalid content in the swap file
178 call writefile([repeat('1', 2*1024)], '.Xfile1.swp')
179 call assert_fails('recover Xfile1', 'E307:')
180 call delete('.Xfile1.swp')
181
182 " :recover using a swap file with a corrupted header
183 edit Xfile1
184 preserve
185 let sn = swapname('')
186 let b = readblob(sn)
Yegappan Lakshmanan99285552021-06-06 17:12:46 +0200187 let save_b = copy(b)
Yegappan Lakshmanan59b26232021-06-05 20:59:22 +0200188 bw!
Yegappan Lakshmanan99285552021-06-06 17:12:46 +0200189 " Run these tests only on little-endian systems. These tests fail on a
190 " big-endian system (IBM S390x system).
191 if b[1008:1011] == 0z33323130
192 \ && b[4096:4097] == 0z7470
193 \ && b[8192:8193] == 0z6164
194
195 " clear the B0_MAGIC_LONG field
196 let b[1008:1011] = 0z00000000
197 call writefile(b, sn)
198 let msg = execute('recover Xfile1')
199 call assert_match('the file has been damaged', msg)
200 bw!
201
202 " clear the pointer ID
203 let b = copy(save_b)
204 let b[4096:4097] = 0z0000
205 call writefile(b, sn)
206 call assert_fails('recover Xfile1', 'E310:')
207 bw!
208
209 " clear the data block ID
210 let b = copy(save_b)
211 let b[8192:8193] = 0z0000
212 call writefile(b, sn)
213 call assert_fails('recover Xfile1', 'E312:')
214 bw!
215
216 " remove the data block
217 let b = copy(save_b)
218 call writefile(b[:8191], sn)
219 call assert_fails('recover Xfile1', 'E312:')
220 endif
221
Yegappan Lakshmanan59b26232021-06-05 20:59:22 +0200222 bw!
223 call delete(sn)
224endfunc
225
226" Test for :recover using an encrypted swap file
227func Test_recover_encrypted_swap_file()
228 CheckUnix
229
230 " Recover an encrypted file from the swap file without the original file
231 new Xfile1
232 call feedkeys(":X\<CR>vim\<CR>vim\<CR>", 'xt')
233 call setline(1, ['aaa', 'bbb', 'ccc'])
234 preserve
235 let b = readblob('.Xfile1.swp')
236 call writefile(b, '.Xfile1.swm')
237 bw!
238 call feedkeys(":recover Xfile1\<CR>vim\<CR>\<CR>", 'xt')
239 call assert_equal(['aaa', 'bbb', 'ccc'], getline(1, '$'))
240 bw!
241 call delete('.Xfile1.swm')
242
243 " Recover an encrypted file from the swap file with the original file
244 new Xfile1
245 call feedkeys(":X\<CR>vim\<CR>vim\<CR>", 'xt')
246 call setline(1, ['aaa', 'bbb', 'ccc'])
247 update
248 call setline(1, ['111', '222', '333'])
249 preserve
250 let b = readblob('.Xfile1.swp')
251 call writefile(b, '.Xfile1.swm')
252 bw!
253 call feedkeys(":recover Xfile1\<CR>vim\<CR>\<CR>", 'xt')
254 call assert_equal(['111', '222', '333'], getline(1, '$'))
255 call assert_true(&modified)
256 bw!
257 call delete('.Xfile1.swm')
258 call delete('Xfile1')
259endfunc
260
261" Test for :recover using a unreadable swap file
262func Test_recover_unreadble_swap_file()
263 CheckUnix
264 CheckNotRoot
265 new Xfile1
266 let b = readblob('.Xfile1.swp')
267 call writefile(b, '.Xfile1.swm')
268 bw!
269 call setfperm('.Xfile1.swm', '-w-------')
270 call assert_fails('recover Xfile1', 'E306:')
271 call delete('.Xfile1.swm')
272endfunc
273
274" Test for using :recover when the original file and the swap file have the
275" same contents.
276func Test_recover_unmodified_file()
277 CheckUnix
278 call writefile(['aaa', 'bbb', 'ccc'], 'Xfile1')
279 edit Xfile1
280 preserve
281 let b = readblob('.Xfile1.swp')
282 %bw!
283 call writefile(b, '.Xfile1.swz')
284 let msg = execute('recover Xfile1')
285 call assert_equal(['aaa', 'bbb', 'ccc'], getline(1, '$'))
286 call assert_false(&modified)
287 call assert_match('Buffer contents equals file contents', msg)
288 bw!
289 call delete('Xfile1')
290 call delete('.Xfile1.swz')
291endfunc
292
Bram Moolenaar6d91bcb2020-08-12 18:50:36 +0200293" vim: shiftwidth=2 sts=2 expandtab