shada_spec.lua (11343B)
1 -- Other ShaDa tests 2 local t = require('test.testutil') 3 local n = require('test.functional.testnvim')() 4 local t_shada = require('test.functional.shada.testutil') 5 local uv = vim.uv 6 local paths = t.paths 7 8 local api, nvim_command, fn, eq = n.api, n.command, n.fn, t.eq 9 local write_file, set_session, exc_exec = t.write_file, n.set_session, n.exc_exec 10 local is_os = t.is_os 11 local skip = t.skip 12 13 local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw 14 local read_shada_file = t_shada.read_shada_file 15 16 local wshada, _, shada_fname, clean = get_shada_rw('Xtest-functional-shada-shada.shada') 17 18 local dirname = 'Xtest-functional-shada-shada.d' 19 local dirshada = dirname .. '/main.shada' 20 21 describe('ShaDa support code', function() 22 before_each(reset) 23 after_each(function() 24 clear() 25 clean() 26 uv.fs_rmdir(dirname) 27 end) 28 29 it('preserves `s` item size limit with unknown entries', function() 30 wshada( 31 '\100\000\207\000\000\000\000\000\000\004\000\218\003\253' 32 .. ('-'):rep(1024 - 3) 33 .. '\100\000\207\000\000\000\000\000\000\004\001\218\003\254' 34 .. ('-'):rep(1025 - 3) 35 ) 36 eq(0, exc_exec('wshada ' .. shada_fname)) 37 local found = 0 38 for _, v in ipairs(read_shada_file(shada_fname)) do 39 if v.type == 100 then 40 found = found + 1 41 end 42 end 43 eq(2, found) 44 eq(0, exc_exec('set shada-=s10 shada+=s1')) 45 eq(0, exc_exec('wshada ' .. shada_fname)) 46 found = 0 47 for _, v in ipairs(read_shada_file(shada_fname)) do 48 if v.type == 100 then 49 found = found + 1 50 end 51 end 52 eq(1, found) 53 end) 54 55 it('preserves `s` item size limit with instance history entries', function() 56 local hist1 = ('-'):rep(1024 - 5) 57 local hist2 = ('-'):rep(1025 - 5) 58 nvim_command('set shada-=s10 shada+=s1') 59 fn.histadd(':', hist1) 60 fn.histadd(':', hist2) 61 eq(0, exc_exec('wshada ' .. shada_fname)) 62 local found = 0 63 for _, v in ipairs(read_shada_file(shada_fname)) do 64 if v.type == 4 then 65 found = found + 1 66 eq(hist1, v.value[2]) 67 end 68 end 69 eq(1, found) 70 end) 71 72 it('leaves .tmp.a in-place when there is error in original ShaDa', function() 73 wshada('Some text file') 74 eq( 75 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', 76 exc_exec('wshada ' .. shada_fname) 77 ) 78 eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type) 79 end) 80 81 it( 82 'does not leave .tmp.a in-place when there is error in original ShaDa, but writing with bang', 83 function() 84 wshada('Some text file') 85 eq(0, exc_exec('wshada! ' .. shada_fname)) 86 eq(1, read_shada_file(shada_fname)[1].type) 87 eq(nil, uv.fs_stat(shada_fname .. '.tmp.a')) 88 end 89 ) 90 91 it('leaves .tmp.b in-place when there is error in original ShaDa and it has .tmp.a', function() 92 wshada('Some text file') 93 eq( 94 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', 95 exc_exec('wshada ' .. shada_fname) 96 ) 97 eq( 98 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', 99 exc_exec('wshada ' .. shada_fname) 100 ) 101 eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type) 102 eq(1, read_shada_file(shada_fname .. '.tmp.b')[1].type) 103 end) 104 105 it( 106 'leaves .tmp.z in-place when there is error in original ShaDa and it has .tmp.a … .tmp.x', 107 function() 108 wshada('Some text file') 109 local i = ('a'):byte() 110 while i < ('z'):byte() do 111 write_file(shada_fname .. ('.tmp.%c'):format(i), 'Some text file', true) 112 i = i + 1 113 end 114 eq( 115 'Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', 116 exc_exec('wshada ' .. shada_fname) 117 ) 118 eq(1, read_shada_file(shada_fname .. '.tmp.z')[1].type) 119 end 120 ) 121 122 it('errors out when there are .tmp.a … .tmp.z ShaDa files', function() 123 wshada('') 124 local i = ('a'):byte() 125 while i <= ('z'):byte() do 126 write_file(shada_fname .. ('.tmp.%c'):format(i), '', true) 127 i = i + 1 128 end 129 eq( 130 'Vim(wshada):E138: All Xtest-functional-shada-shada.shada.tmp.X files exist, cannot write ShaDa file!', 131 exc_exec('wshada ' .. shada_fname) 132 ) 133 end) 134 135 it('reads correctly various timestamps', function() 136 local msgpack = { 137 '\100', -- Positive fixnum 100 138 '\204\255', -- uint 8 255 139 '\205\010\003', -- uint 16 2563 140 '\206\255\010\030\004', -- uint 32 4278853124 141 '\207\005\100\060\250\255\010\030\004', -- uint 64 388502516579048964 142 } 143 local s = '\100' 144 local e = '\001\192' 145 wshada(s .. table.concat(msgpack, e .. s) .. e) 146 eq(0, exc_exec('wshada ' .. shada_fname)) 147 local found = 0 148 local typ = vim.mpack.decode(s) 149 for _, v in ipairs(read_shada_file(shada_fname)) do 150 if v.type == typ then 151 found = found + 1 152 eq(vim.mpack.decode(msgpack[found]), v.timestamp) 153 end 154 end 155 eq(#msgpack, found) 156 end) 157 158 local marklike = { [7] = true, [8] = true, [10] = true, [11] = true } 159 local find_file = function(fname) 160 local found = {} 161 for _, v in ipairs(read_shada_file(shada_fname)) do 162 if marklike[v.type] and v.value.f == fname then 163 found[v.type] = (found[v.type] or 0) + 1 164 elseif v.type == 9 then 165 for _, b in ipairs(v.value) do 166 if b.f == fname then 167 found[v.type] = (found[v.type] or 0) + 1 168 end 169 end 170 end 171 end 172 return found 173 end 174 175 it('correctly uses shada-r option', function() 176 nvim_command('set shellslash') 177 api.nvim_set_var('__home', paths.test_source_path) 178 nvim_command('let $HOME = __home') 179 nvim_command('unlet __home') 180 nvim_command('edit ~/README.md') 181 nvim_command('normal! GmAggmaAabc') 182 nvim_command('undo') 183 nvim_command('set shada+=%') 184 nvim_command('wshada! ' .. shada_fname) 185 local readme_fname = fn.resolve(paths.test_source_path) .. '/README.md' 186 eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 1 }, find_file(readme_fname)) 187 nvim_command('set shada+=r~') 188 nvim_command('wshada! ' .. shada_fname) 189 eq({}, find_file(readme_fname)) 190 nvim_command('set shada-=r~') 191 nvim_command('wshada! ' .. shada_fname) 192 eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 1 }, find_file(readme_fname)) 193 nvim_command('set shada+=r' .. fn.escape(fn.escape(paths.test_source_path, '$~'), ' "\\,')) 194 nvim_command('wshada! ' .. shada_fname) 195 eq({}, find_file(readme_fname)) 196 end) 197 198 it('correctly ignores case with shada-r option', function() 199 nvim_command('set shellslash') 200 local pwd = fn.getcwd() 201 local relfname = 'абв/test' 202 local fname = pwd .. '/' .. relfname 203 api.nvim_set_var('__fname', fname) 204 nvim_command('silent! edit `=__fname`') 205 fn.setline(1, { 'a', 'b', 'c', 'd' }) 206 nvim_command('normal! GmAggmaAabc') 207 nvim_command('undo') 208 nvim_command('set shada+=%') 209 nvim_command('wshada! ' .. shada_fname) 210 eq({ [7] = 2, [8] = 2, [9] = 1, [10] = 4, [11] = 2 }, find_file(fname)) 211 nvim_command('set shada+=r' .. pwd .. '/АБВ') 212 nvim_command('wshada! ' .. shada_fname) 213 eq({}, find_file(fname)) 214 end) 215 216 it("does not store 'nobuflisted' buffer", function() 217 nvim_command('set shellslash') 218 local fname = fn.getcwd() .. '/file' 219 api.nvim_set_var('__fname', fname) 220 nvim_command('edit `=__fname`') 221 api.nvim_set_option_value('buflisted', false, {}) 222 nvim_command('wshada! ' .. shada_fname) 223 eq({}, find_file(fname)) 224 -- Set 'buflisted', then check again. 225 api.nvim_set_option_value('buflisted', true, {}) 226 nvim_command('wshada! ' .. shada_fname) 227 eq({ [7] = 1, [8] = 1, [10] = 1 }, find_file(fname)) 228 end) 229 230 it('is able to set &shada after &viminfo', function() 231 api.nvim_set_option_value('viminfo', "'10", {}) 232 eq("'10", api.nvim_get_option_value('viminfo', {})) 233 eq("'10", api.nvim_get_option_value('shada', {})) 234 api.nvim_set_option_value('shada', '', {}) 235 eq('', api.nvim_get_option_value('viminfo', {})) 236 eq('', api.nvim_get_option_value('shada', {})) 237 end) 238 239 it('is able to set all& after setting &shada', function() 240 api.nvim_set_option_value('shada', "'10", {}) 241 eq("'10", api.nvim_get_option_value('viminfo', {})) 242 eq("'10", api.nvim_get_option_value('shada', {})) 243 nvim_command('set all&') 244 eq("!,'100,<50,s10,h,r/tmp/,r/private/", api.nvim_get_option_value('viminfo', {})) 245 eq("!,'100,<50,s10,h,r/tmp/,r/private/", api.nvim_get_option_value('shada', {})) 246 end) 247 248 it('is able to set &shada after &viminfo using :set', function() 249 nvim_command("set viminfo='10") 250 eq("'10", api.nvim_get_option_value('viminfo', {})) 251 eq("'10", api.nvim_get_option_value('shada', {})) 252 nvim_command('set shada=') 253 eq('', api.nvim_get_option_value('viminfo', {})) 254 eq('', api.nvim_get_option_value('shada', {})) 255 end) 256 257 it('setting &shada gives proper error message on missing number', function() 258 eq([[Vim(set):E526: Missing number after <">: shada="]], exc_exec([[set shada=\"]])) 259 for _, c in ipairs({ "'", '/', ':', '<', '@', 's' }) do 260 eq( 261 ([[Vim(set):E526: Missing number after <%s>: shada=%s]]):format(c, c), 262 exc_exec(([[set shada=%s]]):format(c)) 263 ) 264 end 265 end) 266 267 it('":wshada/:rshada [filename]" works when shadafile=NONE', function() 268 nvim_command('set shadafile=NONE') 269 nvim_command('wshada ' .. shada_fname) 270 eq(1, read_shada_file(shada_fname)[1].type) 271 272 wshada('Some text file') 273 eq( 274 'Vim(rshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', 275 t.pcall_err(n.command, 'rshada ' .. shada_fname) 276 ) 277 end) 278 279 it(':wshada/:rshada without arguments is no-op when shadafile=NONE', function() 280 nvim_command('set shadafile=NONE') 281 nvim_command('wshada') 282 nvim_command('rshada') 283 end) 284 285 it('does not crash when ShaDa file directory is not writable', function() 286 skip(is_os('win')) 287 288 fn.mkdir(dirname, '', '0') 289 eq(0, fn.filewritable(dirname)) 290 reset { shadafile = dirshada, args = { '--cmd', 'set shada=' } } 291 api.nvim_set_option_value('shada', "'10", {}) 292 eq( 293 'Vim(wshada):E886: System error while opening ShaDa file ' 294 .. 'Xtest-functional-shada-shada.d/main.shada for reading to merge ' 295 .. 'before writing it: permission denied', 296 exc_exec('wshada') 297 ) 298 api.nvim_set_option_value('shada', '', {}) 299 end) 300 end) 301 302 describe('ShaDa support code', function() 303 it('does not write NONE file', function() 304 local session = n.new_session(false, { 305 merge = false, 306 args = { '-u', 'NONE', '-i', 'NONE', '--embed', '--headless', '--cmd', 'qall' }, 307 }) 308 session:close() 309 eq(nil, uv.fs_stat('NONE')) 310 eq(nil, uv.fs_stat('NONE.tmp.a')) 311 end) 312 313 it('does not read NONE file', function() 314 write_file('NONE', '\005\001\015\131\161na\162rX\194\162rc\145\196\001-') 315 local session = n.new_session( 316 false, 317 { merge = false, args = { '-u', 'NONE', '-i', 'NONE', '--embed', '--headless' } } 318 ) 319 set_session(session) 320 eq('', fn.getreg('a')) 321 session:close() 322 os.remove('NONE') 323 end) 324 end)