neovim

Neovim text editor
git clone https://git.dasho.dev/neovim.git
Log | Files | Refs | README

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)