1-- Other ShaDa tests 2local helpers = require('test.functional.helpers')(after_each) 3local meths, nvim_command, funcs, eq = 4 helpers.meths, helpers.command, helpers.funcs, helpers.eq 5local write_file, spawn, set_session, nvim_prog, exc_exec = 6 helpers.write_file, helpers.spawn, helpers.set_session, helpers.nvim_prog, 7 helpers.exc_exec 8 9local lfs = require('lfs') 10local paths = require('test.config.paths') 11 12local mpack = require('mpack') 13 14local shada_helpers = require('test.functional.shada.helpers') 15local reset, clear, get_shada_rw = 16 shada_helpers.reset, shada_helpers.clear, shada_helpers.get_shada_rw 17local read_shada_file = shada_helpers.read_shada_file 18 19local wshada, _, shada_fname, clean = 20 get_shada_rw('Xtest-functional-shada-shada.shada') 21 22local dirname = 'Xtest-functional-shada-shada.d' 23local dirshada = dirname .. '/main.shada' 24 25describe('ShaDa support code', function() 26 before_each(reset) 27 after_each(function() 28 clear() 29 clean() 30 lfs.rmdir(dirname) 31 end) 32 33 it('preserves `s` item size limit with unknown entries', function() 34 wshada('\100\000\207\000\000\000\000\000\000\004\000\218\003\253' .. ('-'):rep(1024 - 3) 35 .. '\100\000\207\000\000\000\000\000\000\004\001\218\003\254' .. ('-'):rep(1025 - 3)) 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 funcs.histadd(':', hist1) 60 funcs.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('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname)) 75 eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type) 76 end) 77 78 it('does not leave .tmp.a in-place when there is error in original ShaDa, but writing with bang', function() 79 wshada('Some text file') 80 eq(0, exc_exec('wshada! ' .. shada_fname)) 81 eq(1, read_shada_file(shada_fname)[1].type) 82 eq(nil, lfs.attributes(shada_fname .. '.tmp.a')) 83 end) 84 85 it('leaves .tmp.b in-place when there is error in original ShaDa and it has .tmp.a', function() 86 wshada('Some text file') 87 eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname)) 88 eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname)) 89 eq(1, read_shada_file(shada_fname .. '.tmp.a')[1].type) 90 eq(1, read_shada_file(shada_fname .. '.tmp.b')[1].type) 91 end) 92 93 it('leaves .tmp.z in-place when there is error in original ShaDa and it has .tmp.a … .tmp.x', function() 94 wshada('Some text file') 95 local i = ('a'):byte() 96 while i < ('z'):byte() do 97 write_file(shada_fname .. ('.tmp.%c'):format(i), 'Some text file', true) 98 i = i + 1 99 end 100 eq('Vim(wshada):E576: Error while reading ShaDa file: last entry specified that it occupies 109 bytes, but file ended earlier', exc_exec('wshada ' .. shada_fname)) 101 eq(1, read_shada_file(shada_fname .. '.tmp.z')[1].type) 102 end) 103 104 it('errors out when there are .tmp.a … .tmp.z ShaDa files', function() 105 wshada('') 106 local i = ('a'):byte() 107 while i <= ('z'):byte() do 108 write_file(shada_fname .. ('.tmp.%c'):format(i), '', true) 109 i = i + 1 110 end 111 eq('Vim(wshada):E138: All Xtest-functional-shada-shada.shada.tmp.X files exist, cannot write ShaDa file!', exc_exec('wshada ' .. shada_fname)) 112 end) 113 114 it('reads correctly various timestamps', function() 115 local msgpack = { 116 '\100', -- Positive fixnum 100 117 '\204\255', -- uint 8 255 118 '\205\010\003', -- uint 16 2563 119 '\206\255\010\030\004', -- uint 32 4278853124 120 '\207\005\100\060\250\255\010\030\004', -- uint 64 388502516579048964 121 } 122 local s = '\100' 123 local e = '\001\192' 124 wshada(s .. table.concat(msgpack, e .. s) .. e) 125 eq(0, exc_exec('wshada ' .. shada_fname)) 126 local found = 0 127 local typ = mpack.unpack(s) 128 for _, v in ipairs(read_shada_file(shada_fname)) do 129 if v.type == typ then 130 found = found + 1 131 eq(mpack.unpack(msgpack[found]), v.timestamp) 132 end 133 end 134 eq(#msgpack, found) 135 end) 136 137 it('does not write NONE file', function() 138 local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', 139 '--headless', '--cmd', 'qall'}, true) 140 session:close() 141 eq(nil, lfs.attributes('NONE')) 142 eq(nil, lfs.attributes('NONE.tmp.a')) 143 end) 144 145 it('does not read NONE file', function() 146 write_file('NONE', '\005\001\015\131\161na\162rX\194\162rc\145\196\001-') 147 local session = spawn({nvim_prog, '-u', 'NONE', '-i', 'NONE', '--embed', 148 '--headless'}, true) 149 set_session(session) 150 eq('', funcs.getreg('a')) 151 session:close() 152 os.remove('NONE') 153 end) 154 155 local marklike = {[7]=true, [8]=true, [10]=true, [11]=true} 156 local find_file = function(fname) 157 local found = {} 158 for _, v in ipairs(read_shada_file(shada_fname)) do 159 if marklike[v.type] and v.value.f == fname then 160 found[v.type] = (found[v.type] or 0) + 1 161 elseif v.type == 9 then 162 for _, b in ipairs(v.value) do 163 if b.f == fname then 164 found[v.type] = (found[v.type] or 0) + 1 165 end 166 end 167 end 168 end 169 return found 170 end 171 172 it('correctly uses shada-r option', function() 173 nvim_command('set shellslash') 174 meths.set_var('__home', paths.test_source_path) 175 nvim_command('let $HOME = __home') 176 nvim_command('unlet __home') 177 nvim_command('edit ~/README.md') 178 nvim_command('normal! GmAggmaAabc') 179 nvim_command('undo') 180 nvim_command('set shada+=%') 181 nvim_command('wshada! ' .. shada_fname) 182 local readme_fname = funcs.resolve(paths.test_source_path) .. '/README.md' 183 eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname)) 184 nvim_command('set shada+=r~') 185 nvim_command('wshada! ' .. shada_fname) 186 eq({}, find_file(readme_fname)) 187 nvim_command('set shada-=r~') 188 nvim_command('wshada! ' .. shada_fname) 189 eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=1}, find_file(readme_fname)) 190 nvim_command('set shada+=r' .. funcs.escape( 191 funcs.escape(paths.test_source_path, '$~'), ' "\\,')) 192 nvim_command('wshada! ' .. shada_fname) 193 eq({}, find_file(readme_fname)) 194 end) 195 196 it('correctly ignores case with shada-r option', function() 197 nvim_command('set shellslash') 198 local pwd = funcs.getcwd() 199 local relfname = 'абв/test' 200 local fname = pwd .. '/' .. relfname 201 meths.set_var('__fname', fname) 202 nvim_command('silent! edit `=__fname`') 203 funcs.setline(1, {'a', 'b', 'c', 'd'}) 204 nvim_command('normal! GmAggmaAabc') 205 nvim_command('undo') 206 nvim_command('set shada+=%') 207 nvim_command('wshada! ' .. shada_fname) 208 eq({[7]=2, [8]=2, [9]=1, [10]=4, [11]=2}, find_file(fname)) 209 nvim_command('set shada+=r' .. pwd .. '/АБВ') 210 nvim_command('wshada! ' .. shada_fname) 211 eq({}, find_file(fname)) 212 end) 213 214 it('is able to set &shada after &viminfo', function() 215 meths.set_option('viminfo', '\'10') 216 eq('\'10', meths.get_option('viminfo')) 217 eq('\'10', meths.get_option('shada')) 218 meths.set_option('shada', '') 219 eq('', meths.get_option('viminfo')) 220 eq('', meths.get_option('shada')) 221 end) 222 223 it('is able to set all& after setting &shada', function() 224 meths.set_option('shada', '\'10') 225 eq('\'10', meths.get_option('viminfo')) 226 eq('\'10', meths.get_option('shada')) 227 nvim_command('set all&') 228 eq('!,\'100,<50,s10,h', meths.get_option('viminfo')) 229 eq('!,\'100,<50,s10,h', meths.get_option('shada')) 230 end) 231 232 it('is able to set &shada after &viminfo using :set', function() 233 nvim_command('set viminfo=\'10') 234 eq('\'10', meths.get_option('viminfo')) 235 eq('\'10', meths.get_option('shada')) 236 nvim_command('set shada=') 237 eq('', meths.get_option('viminfo')) 238 eq('', meths.get_option('shada')) 239 end) 240 241 it('does not crash when ShaDa file directory is not writable', function() 242 if helpers.pending_win32(pending) then return end 243 244 funcs.mkdir(dirname, '', 0) 245 eq(0, funcs.filewritable(dirname)) 246 reset{shadafile=dirshada, args={'--cmd', 'set shada='}} 247 meths.set_option('shada', '\'10') 248 eq('Vim(wshada):E886: System error while opening ShaDa file ' 249 .. 'Xtest-functional-shada-shada.d/main.shada for reading to merge ' 250 .. 'before writing it: permission denied', 251 exc_exec('wshada')) 252 meths.set_option('shada', '') 253 end) 254end) 255