neovim

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

merging_spec.lua (40561B)


      1 -- ShaDa merging data support
      2 local t = require('test.testutil')
      3 local n = require('test.functional.testnvim')()
      4 local t_shada = require('test.functional.shada.testutil')
      5 
      6 local nvim_command, fn, eq = n.command, n.fn, t.eq
      7 local exc_exec, exec_capture = n.exc_exec, n.exec_capture
      8 local api = n.api
      9 
     10 local reset, clear, get_shada_rw = t_shada.reset, t_shada.clear, t_shada.get_shada_rw
     11 local read_shada_file = t_shada.read_shada_file
     12 
     13 local wshada, sdrcmd, shada_fname = get_shada_rw('Xtest-functional-shada-merging.shada')
     14 
     15 local mock_file_path = '/a/b/'
     16 if t.is_os('win') then
     17  mock_file_path = 'C:/a/'
     18 end
     19 
     20 describe('ShaDa history merging code', function()
     21  before_each(reset)
     22  after_each(function()
     23    clear()
     24    os.remove(shada_fname)
     25  end)
     26 
     27  it('takes item with greater timestamp from Neovim instance when reading', function()
     28    wshada('\004\001\009\147\000\196\002ab\196\001a')
     29    eq(0, exc_exec(sdrcmd()))
     30    wshada('\004\000\009\147\000\196\002ab\196\001b')
     31    eq(0, exc_exec(sdrcmd()))
     32    os.remove(shada_fname)
     33    eq(0, exc_exec('wshada! ' .. shada_fname))
     34    local found = 0
     35    for _, v in ipairs(read_shada_file(shada_fname)) do
     36      if v.type == 4 and v.value[1] == 0 and v.value[2] == 'ab' then
     37        eq(1, v.timestamp)
     38        eq('a', v.value[3])
     39        found = found + 1
     40      end
     41    end
     42    eq(1, found)
     43  end)
     44 
     45  it('takes item with equal timestamp from Neovim instance when reading', function()
     46    wshada('\004\000\009\147\000\196\002ab\196\001a')
     47    eq(0, exc_exec(sdrcmd()))
     48    wshada('\004\000\009\147\000\196\002ab\196\001b')
     49    eq(0, exc_exec(sdrcmd()))
     50    os.remove(shada_fname)
     51    eq(0, exc_exec('wshada! ' .. shada_fname))
     52    local found = 0
     53    for _, v in ipairs(read_shada_file(shada_fname)) do
     54      if v.type == 4 and v.value[1] == 0 and v.value[2] == 'ab' then
     55        eq(0, v.timestamp)
     56        eq('a', v.value[3])
     57        found = found + 1
     58      end
     59    end
     60    eq(1, found)
     61  end)
     62 
     63  it('takes item with greater timestamp from ShaDa when reading', function()
     64    wshada('\004\000\009\147\000\196\002ab\196\001a')
     65    eq(0, exc_exec(sdrcmd()))
     66    wshada('\004\001\009\147\000\196\002ab\196\001b')
     67    eq(0, exc_exec(sdrcmd()))
     68    os.remove(shada_fname)
     69    eq(0, exc_exec('wshada! ' .. shada_fname))
     70    local found = 0
     71    for _, v in ipairs(read_shada_file(shada_fname)) do
     72      if v.type == 4 and v.value[1] == 0 and v.value[2] == 'ab' then
     73        eq(1, v.timestamp)
     74        eq('b', v.value[3])
     75        found = found + 1
     76      end
     77    end
     78    eq(1, found)
     79  end)
     80 
     81  it('takes item with greater timestamp from Neovim instance when writing', function()
     82    wshada('\004\001\009\147\000\196\002ab\196\001a')
     83    eq(0, exc_exec(sdrcmd()))
     84    wshada('\004\000\009\147\000\196\002ab\196\001b')
     85    eq(0, exc_exec('wshada ' .. shada_fname))
     86    local found = 0
     87    for _, v in ipairs(read_shada_file(shada_fname)) do
     88      if v.type == 4 and v.value[1] == 0 and v.value[2] == 'ab' then
     89        eq(1, v.timestamp)
     90        eq('a', v.value[3])
     91        found = found + 1
     92      end
     93    end
     94    eq(1, found)
     95  end)
     96 
     97  it('takes item with equal timestamp from Neovim instance when writing', function()
     98    wshada('\004\000\009\147\000\196\002ab\196\001a')
     99    eq(0, exc_exec(sdrcmd()))
    100    wshada('\004\000\009\147\000\196\002ab\196\001b')
    101    eq(0, exc_exec('wshada ' .. shada_fname))
    102    local found = 0
    103    for _, v in ipairs(read_shada_file(shada_fname)) do
    104      if v.type == 4 and v.value[1] == 0 and v.value[2] == 'ab' then
    105        eq(0, v.timestamp)
    106        eq('a', v.value[3])
    107        found = found + 1
    108      end
    109    end
    110    eq(1, found)
    111  end)
    112 
    113  it('takes item with greater timestamp from ShaDa when writing', function()
    114    wshada('\004\000\009\147\000\196\002ab\196\001a')
    115    eq(0, exc_exec(sdrcmd()))
    116    wshada('\004\001\009\147\000\196\002ab\196\001b')
    117    eq(0, exc_exec('wshada ' .. shada_fname))
    118    local found = 0
    119    for _, v in ipairs(read_shada_file(shada_fname)) do
    120      if v.type == 4 and v.value[1] == 0 and v.value[2] == 'ab' then
    121        eq(1, v.timestamp)
    122        eq('b', v.value[3])
    123        found = found + 1
    124      end
    125    end
    126    eq(1, found)
    127  end)
    128 
    129  it('correctly reads history items with messed up timestamps', function()
    130    wshada(
    131      '\004\010\009\147\000\196\002ab\196\001a'
    132        .. '\004\010\009\147\000\196\002ac\196\001a'
    133        .. '\004\005\009\147\000\196\002ad\196\001a'
    134        .. '\004\100\009\147\000\196\002ae\196\001a'
    135        .. '\004\090\009\147\000\196\002af\196\001a'
    136    )
    137    eq(0, exc_exec(sdrcmd()))
    138    os.remove(shada_fname)
    139    eq(0, exc_exec('wshada! ' .. shada_fname))
    140    local items = { 'ad', 'ab', 'ac', 'af', 'ae' }
    141    for i, v in ipairs(items) do
    142      eq(v, fn.histget(':', i))
    143    end
    144    local found = 0
    145    for _, v in ipairs(read_shada_file(shada_fname)) do
    146      if v.type == 4 and v.value[1] == 0 then
    147        found = found + 1
    148        eq(items[found], v.value[2])
    149        eq('a', v.value[3])
    150      end
    151    end
    152    eq(#items, found)
    153  end)
    154 
    155  it('correctly reorders history items with messed up timestamps when writing', function()
    156    wshada(
    157      '\004\010\009\147\000\196\002ab\196\001a'
    158        .. '\004\010\009\147\000\196\002ac\196\001a'
    159        .. '\004\005\009\147\000\196\002ad\196\001a'
    160        .. '\004\100\009\147\000\196\002ae\196\001a'
    161        .. '\004\090\009\147\000\196\002af\196\001a'
    162    )
    163    eq(0, exc_exec('wshada ' .. shada_fname))
    164    local items = { 'ad', 'ab', 'ac', 'af', 'ae' }
    165    local found = 0
    166    for _, v in ipairs(read_shada_file(shada_fname)) do
    167      if v.type == 4 and v.value[1] == 0 then
    168        found = found + 1
    169        eq(items[found], v.value[2])
    170        eq('a', v.value[3])
    171      end
    172    end
    173    eq(#items, found)
    174  end)
    175 
    176  it('correctly merges history items with duplicate mid entry when writing', function()
    177    -- Regression test: ShaDa code used to crash here.
    178    -- Conditions:
    179    -- 1. Entry which is duplicate to non-last entry.
    180    -- 2. At least one more non-duplicate entry.
    181    wshada(
    182      '\004\000\009\147\000\196\002ab\196\001a'
    183        .. '\004\001\009\147\000\196\002ac\196\001a'
    184        .. '\004\002\009\147\000\196\002ad\196\001a'
    185        .. '\004\003\009\147\000\196\002ac\196\001a'
    186        .. '\004\004\009\147\000\196\002af\196\001a'
    187        .. '\004\005\009\147\000\196\002ae\196\001a'
    188        .. '\004\006\009\147\000\196\002ag\196\001a'
    189        .. '\004\007\009\147\000\196\002ah\196\001a'
    190        .. '\004\008\009\147\000\196\002ai\196\001a'
    191    )
    192    eq(0, exc_exec('wshada ' .. shada_fname))
    193    local items = { 'ab', 'ad', 'ac', 'af', 'ae', 'ag', 'ah', 'ai' }
    194    local found = 0
    195    for _, v in ipairs(read_shada_file(shada_fname)) do
    196      if v.type == 4 and v.value[1] == 0 then
    197        found = found + 1
    198        eq(items[found], v.value[2])
    199        eq('a', v.value[3])
    200      end
    201    end
    202    eq(#items, found)
    203  end)
    204 
    205  it('correctly merges history items with duplicate adj entry when writing', function()
    206    wshada(
    207      '\004\000\009\147\000\196\002ab\196\001a'
    208        .. '\004\001\009\147\000\196\002ac\196\001a'
    209        .. '\004\002\009\147\000\196\002ad\196\001a'
    210        .. '\004\003\009\147\000\196\002ad\196\001a'
    211        .. '\004\004\009\147\000\196\002af\196\001a'
    212        .. '\004\005\009\147\000\196\002ae\196\001a'
    213        .. '\004\006\009\147\000\196\002ag\196\001a'
    214        .. '\004\007\009\147\000\196\002ah\196\001a'
    215        .. '\004\008\009\147\000\196\002ai\196\001a'
    216    )
    217    eq(0, exc_exec('wshada ' .. shada_fname))
    218    local items = { 'ab', 'ac', 'ad', 'af', 'ae', 'ag', 'ah', 'ai' }
    219    local found = 0
    220    for _, v in ipairs(read_shada_file(shada_fname)) do
    221      if v.type == 4 and v.value[1] == 0 then
    222        found = found + 1
    223        eq(items[found], v.value[2])
    224        eq('a', v.value[3])
    225      end
    226    end
    227    eq(#items, found)
    228  end)
    229 end)
    230 
    231 describe('ShaDa search pattern support code', function()
    232  before_each(reset)
    233  after_each(function()
    234    clear()
    235    os.remove(shada_fname)
    236  end)
    237 
    238  it('uses last search pattern with gt timestamp from instance when reading', function()
    239    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    240    eq(0, exc_exec(sdrcmd()))
    241    wshada('\002\000\011\130\162sX\194\162sp\196\001?')
    242    eq(0, exc_exec(sdrcmd()))
    243    eq('-', fn.getreg('/'))
    244  end)
    245 
    246  it('uses last search pattern with gt tstamp from file when reading with bang', function()
    247    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    248    eq(0, exc_exec(sdrcmd()))
    249    wshada('\002\000\011\130\162sX\194\162sp\196\001?')
    250    eq(0, exc_exec(sdrcmd(true)))
    251    eq('?', fn.getreg('/'))
    252  end)
    253 
    254  it('uses last search pattern with eq timestamp from instance when reading', function()
    255    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    256    eq(0, exc_exec(sdrcmd()))
    257    wshada('\002\001\011\130\162sX\194\162sp\196\001?')
    258    eq(0, exc_exec(sdrcmd()))
    259    eq('-', fn.getreg('/'))
    260  end)
    261 
    262  it('uses last search pattern with gt timestamp from file when reading', function()
    263    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    264    eq(0, exc_exec(sdrcmd()))
    265    wshada('\002\002\011\130\162sX\194\162sp\196\001?')
    266    eq(0, exc_exec(sdrcmd()))
    267    eq('?', fn.getreg('/'))
    268  end)
    269 
    270  it('uses last search pattern with gt timestamp from instance when writing', function()
    271    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    272    eq(0, exc_exec(sdrcmd()))
    273    wshada('\002\000\011\130\162sX\194\162sp\196\001?')
    274    eq('-', fn.getreg('/'))
    275    eq(0, exc_exec('wshada ' .. shada_fname))
    276    local found = 0
    277    for _, v in ipairs(read_shada_file(shada_fname)) do
    278      if v.type == 2 and v.value.sp == '-' then
    279        found = found + 1
    280      end
    281    end
    282    eq(1, found)
    283  end)
    284 
    285  it('uses last search pattern with eq timestamp from instance when writing', function()
    286    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    287    eq(0, exc_exec(sdrcmd()))
    288    wshada('\002\001\011\130\162sX\194\162sp\196\001?')
    289    eq('-', fn.getreg('/'))
    290    eq(0, exc_exec('wshada ' .. shada_fname))
    291    local found = 0
    292    for _, v in ipairs(read_shada_file(shada_fname)) do
    293      if v.type == 2 and v.value.sp == '-' then
    294        found = found + 1
    295      end
    296    end
    297    eq(1, found)
    298  end)
    299 
    300  it('uses last search pattern with gt timestamp from file when writing', function()
    301    wshada('\002\001\011\130\162sX\194\162sp\196\001-')
    302    eq(0, exc_exec(sdrcmd()))
    303    wshada('\002\002\011\130\162sX\194\162sp\196\001?')
    304    eq('-', fn.getreg('/'))
    305    eq(0, exc_exec('wshada ' .. shada_fname))
    306    local found = 0
    307    for _, v in ipairs(read_shada_file(shada_fname)) do
    308      if v.type == 2 and v.value.sp == '?' then
    309        found = found + 1
    310      end
    311    end
    312    eq(1, found)
    313  end)
    314 
    315  it('uses last s/ pattern with gt timestamp from instance when reading', function()
    316    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    317    eq(0, exc_exec(sdrcmd()))
    318    wshada('\002\000\011\130\162ss\195\162sp\196\001?')
    319    eq(0, exc_exec(sdrcmd()))
    320    eq('-', fn.getreg('/'))
    321  end)
    322 
    323  it('uses last s/ pattern with gt timestamp from file when reading with !', function()
    324    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    325    eq(0, exc_exec(sdrcmd()))
    326    wshada('\002\000\011\130\162ss\195\162sp\196\001?')
    327    eq(0, exc_exec(sdrcmd(true)))
    328    eq('?', fn.getreg('/'))
    329  end)
    330 
    331  it('uses last s/ pattern with eq timestamp from instance when reading', function()
    332    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    333    eq(0, exc_exec(sdrcmd()))
    334    wshada('\002\001\011\130\162ss\195\162sp\196\001?')
    335    eq(0, exc_exec(sdrcmd()))
    336    eq('-', fn.getreg('/'))
    337  end)
    338 
    339  it('uses last s/ pattern with gt timestamp from file when reading', function()
    340    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    341    eq(0, exc_exec(sdrcmd()))
    342    wshada('\002\002\011\130\162ss\195\162sp\196\001?')
    343    eq(0, exc_exec(sdrcmd()))
    344    eq('?', fn.getreg('/'))
    345  end)
    346 
    347  it('uses last s/ pattern with gt timestamp from instance when writing', function()
    348    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    349    eq(0, exc_exec(sdrcmd()))
    350    wshada('\002\000\011\130\162ss\195\162sp\196\001?')
    351    eq('-', fn.getreg('/'))
    352    eq(0, exc_exec('wshada ' .. shada_fname))
    353    local found = 0
    354    for _, v in ipairs(read_shada_file(shada_fname)) do
    355      if v.type == 2 and v.value.sp == '-' then
    356        found = found + 1
    357      end
    358    end
    359    eq(1, found)
    360  end)
    361 
    362  it('uses last s/ pattern with eq timestamp from instance when writing', function()
    363    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    364    eq(0, exc_exec(sdrcmd()))
    365    wshada('\002\001\011\130\162ss\195\162sp\196\001?')
    366    eq('-', fn.getreg('/'))
    367    eq(0, exc_exec('wshada ' .. shada_fname))
    368    local found = 0
    369    for _, v in ipairs(read_shada_file(shada_fname)) do
    370      if v.type == 2 and v.value.sp == '-' then
    371        found = found + 1
    372      end
    373    end
    374    eq(1, found)
    375  end)
    376 
    377  it('uses last s/ pattern with gt timestamp from file when writing', function()
    378    wshada('\002\001\011\130\162ss\195\162sp\196\001-')
    379    eq(0, exc_exec(sdrcmd()))
    380    wshada('\002\002\011\130\162ss\195\162sp\196\001?')
    381    eq('-', fn.getreg('/'))
    382    eq(0, exc_exec('wshada ' .. shada_fname))
    383    local found = 0
    384    for _, v in ipairs(read_shada_file(shada_fname)) do
    385      if v.type == 2 and v.value.sp == '?' then
    386        found = found + 1
    387      end
    388    end
    389    eq(1, found)
    390  end)
    391 end)
    392 
    393 describe('ShaDa replacement string support code', function()
    394  before_each(reset)
    395  after_each(function()
    396    clear()
    397    os.remove(shada_fname)
    398  end)
    399 
    400  it('uses last replacement with gt timestamp from instance when reading', function()
    401    wshada('\003\001\004\145\196\001-')
    402    eq(0, exc_exec(sdrcmd()))
    403    wshada('\003\000\004\145\196\001?')
    404    eq(0, exc_exec(sdrcmd()))
    405    nvim_command('s/.*/~')
    406    eq('-', fn.getline('.'))
    407    nvim_command('bwipeout!')
    408  end)
    409 
    410  it('uses last replacement with gt timestamp from file when reading with bang', function()
    411    wshada('\003\001\004\145\196\001-')
    412    eq(0, exc_exec(sdrcmd()))
    413    wshada('\003\000\004\145\196\001?')
    414    eq(0, exc_exec(sdrcmd(true)))
    415    nvim_command('s/.*/~')
    416    eq('?', fn.getline('.'))
    417    nvim_command('bwipeout!')
    418  end)
    419 
    420  it('uses last replacement with eq timestamp from instance when reading', function()
    421    wshada('\003\001\004\145\196\001-')
    422    eq(0, exc_exec(sdrcmd()))
    423    wshada('\003\001\004\145\196\001?')
    424    eq(0, exc_exec(sdrcmd()))
    425    nvim_command('s/.*/~')
    426    eq('-', fn.getline('.'))
    427    nvim_command('bwipeout!')
    428  end)
    429 
    430  it('uses last replacement with gt timestamp from file when reading', function()
    431    wshada('\003\001\004\145\196\001-')
    432    eq(0, exc_exec(sdrcmd()))
    433    wshada('\003\002\004\145\196\001?')
    434    eq(0, exc_exec(sdrcmd()))
    435    nvim_command('s/.*/~')
    436    eq('?', fn.getline('.'))
    437    nvim_command('bwipeout!')
    438  end)
    439 
    440  it('uses last replacement with gt timestamp from instance when writing', function()
    441    wshada('\003\001\004\145\196\001-')
    442    eq(0, exc_exec(sdrcmd()))
    443    wshada('\003\000\004\145\196\001?')
    444    eq(0, exc_exec('wshada ' .. shada_fname))
    445    local found = 0
    446    for _, v in ipairs(read_shada_file(shada_fname)) do
    447      if v.type == 3 and v.value[1] == '-' then
    448        found = found + 1
    449      end
    450    end
    451    eq(1, found)
    452  end)
    453 
    454  it('uses last replacement with eq timestamp from instance when writing', function()
    455    wshada('\003\001\004\145\196\001-')
    456    eq(0, exc_exec(sdrcmd()))
    457    wshada('\003\001\004\145\196\001?')
    458    eq(0, exc_exec('wshada ' .. shada_fname))
    459    local found = 0
    460    for _, v in ipairs(read_shada_file(shada_fname)) do
    461      if v.type == 3 and v.value[1] == '-' then
    462        found = found + 1
    463      end
    464    end
    465    eq(1, found)
    466  end)
    467 
    468  it('uses last replacement with gt timestamp from file when writing', function()
    469    wshada('\003\001\004\145\196\001-')
    470    eq(0, exc_exec(sdrcmd()))
    471    wshada('\003\002\004\145\196\001?')
    472    eq(0, exc_exec('wshada ' .. shada_fname))
    473    local found = 0
    474    for _, v in ipairs(read_shada_file(shada_fname)) do
    475      if v.type == 3 and v.value[1] == '?' then
    476        found = found + 1
    477      end
    478    end
    479    eq(1, found)
    480  end)
    481 end)
    482 
    483 describe('ShaDa marks support code', function()
    484  before_each(reset)
    485  after_each(function()
    486    clear()
    487    os.remove(shada_fname)
    488  end)
    489 
    490  it('uses last A mark with gt timestamp from instance when reading', function()
    491    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    492    eq(0, exc_exec(sdrcmd()))
    493    wshada('\007\000\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    494    eq(0, exc_exec(sdrcmd()))
    495    nvim_command('normal! `A')
    496    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    497  end)
    498 
    499  it('can merge with file with mark 9 as the only numeric mark', function()
    500    wshada('\007\001\014\130\161f\196\006' .. mock_file_path .. '-\161n9')
    501    eq(0, exc_exec(sdrcmd()))
    502    nvim_command('normal! `9oabc')
    503    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    504    eq(0, exc_exec('wshada ' .. shada_fname))
    505    local found = {}
    506    for _, v in ipairs(read_shada_file(shada_fname)) do
    507      if v.type == 7 and v.value.f == mock_file_path .. '-' then
    508        local name = ('%c'):format(v.value.n)
    509        found[name] = (found[name] or 0) + 1
    510      end
    511    end
    512    eq({ ['0'] = 1, ['1'] = 1 }, found)
    513  end)
    514 
    515  it('removes duplicates while merging', function()
    516    wshada(
    517      '\007\001\014\130\161f\196\006'
    518        .. mock_file_path
    519        .. '-\161n9'
    520        .. '\007\001\014\130\161f\196\006'
    521        .. mock_file_path
    522        .. '-\161n9'
    523    )
    524    eq(0, exc_exec(sdrcmd()))
    525    eq(0, exc_exec('wshada ' .. shada_fname))
    526    local found = 0
    527    for _, v in ipairs(read_shada_file(shada_fname)) do
    528      if v.type == 7 and v.value.f == mock_file_path .. '-' then
    529        print(require('test.format_string').format_luav(v))
    530        found = found + 1
    531      end
    532    end
    533    eq(1, found)
    534  end)
    535 
    536  it('does not leak when no append is performed due to too many marks', function()
    537    wshada(
    538      '\007\002\018\131\162mX\195\161f\196\006'
    539        .. mock_file_path
    540        .. 'a\161n0'
    541        .. '\007\002\018\131\162mX\195\161f\196\006'
    542        .. mock_file_path
    543        .. 'b\161n1'
    544        .. '\007\002\018\131\162mX\195\161f\196\006'
    545        .. mock_file_path
    546        .. 'c\161n2'
    547        .. '\007\002\018\131\162mX\195\161f\196\006'
    548        .. mock_file_path
    549        .. 'd\161n3'
    550        .. '\007\002\018\131\162mX\195\161f\196\006'
    551        .. mock_file_path
    552        .. 'e\161n4'
    553        .. '\007\002\018\131\162mX\195\161f\196\006'
    554        .. mock_file_path
    555        .. 'f\161n5'
    556        .. '\007\002\018\131\162mX\195\161f\196\006'
    557        .. mock_file_path
    558        .. 'g\161n6'
    559        .. '\007\002\018\131\162mX\195\161f\196\006'
    560        .. mock_file_path
    561        .. 'h\161n7'
    562        .. '\007\002\018\131\162mX\195\161f\196\006'
    563        .. mock_file_path
    564        .. 'i\161n8'
    565        .. '\007\002\018\131\162mX\195\161f\196\006'
    566        .. mock_file_path
    567        .. 'j\161n9'
    568        .. '\007\001\018\131\162mX\195\161f\196\006'
    569        .. mock_file_path
    570        .. 'k\161n9'
    571    )
    572    eq(0, exc_exec(sdrcmd()))
    573    eq(0, exc_exec('wshada ' .. shada_fname))
    574    local found = {}
    575    for _, v in ipairs(read_shada_file(shada_fname)) do
    576      if v.type == 7 and v.value.f:sub(1, #mock_file_path) == mock_file_path then
    577        found[#found + 1] = v.value.f:sub(#v.value.f)
    578      end
    579    end
    580    eq({ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j' }, found)
    581  end)
    582 
    583  it('does not leak when last mark in file removes some of the earlier ones', function()
    584    wshada(
    585      '\007\002\018\131\162mX\195\161f\196\006'
    586        .. mock_file_path
    587        .. 'a\161n0'
    588        .. '\007\002\018\131\162mX\195\161f\196\006'
    589        .. mock_file_path
    590        .. 'b\161n1'
    591        .. '\007\002\018\131\162mX\195\161f\196\006'
    592        .. mock_file_path
    593        .. 'c\161n2'
    594        .. '\007\002\018\131\162mX\195\161f\196\006'
    595        .. mock_file_path
    596        .. 'd\161n3'
    597        .. '\007\002\018\131\162mX\195\161f\196\006'
    598        .. mock_file_path
    599        .. 'e\161n4'
    600        .. '\007\002\018\131\162mX\195\161f\196\006'
    601        .. mock_file_path
    602        .. 'f\161n5'
    603        .. '\007\002\018\131\162mX\195\161f\196\006'
    604        .. mock_file_path
    605        .. 'g\161n6'
    606        .. '\007\002\018\131\162mX\195\161f\196\006'
    607        .. mock_file_path
    608        .. 'h\161n7'
    609        .. '\007\002\018\131\162mX\195\161f\196\006'
    610        .. mock_file_path
    611        .. 'i\161n8'
    612        .. '\007\002\018\131\162mX\195\161f\196\006'
    613        .. mock_file_path
    614        .. 'j\161n9'
    615        .. '\007\003\018\131\162mX\195\161f\196\006'
    616        .. mock_file_path
    617        .. 'k\161n9'
    618    )
    619    eq(0, exc_exec(sdrcmd()))
    620    eq(0, exc_exec('wshada ' .. shada_fname))
    621    local found = {}
    622    for _, v in ipairs(read_shada_file(shada_fname)) do
    623      if v.type == 7 and v.value.f:sub(1, #mock_file_path) == mock_file_path then
    624        found[#found + 1] = v.value.f:sub(#v.value.f)
    625      end
    626    end
    627    eq({ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'k' }, found)
    628  end)
    629 
    630  it('uses last A mark with gt timestamp from file when reading with !', function()
    631    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    632    eq(0, exc_exec(sdrcmd()))
    633    wshada('\007\000\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    634    eq(0, exc_exec(sdrcmd(true)))
    635    nvim_command('normal! `A')
    636    eq('?', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    637  end)
    638 
    639  it('uses last A mark with eq timestamp from instance when reading', function()
    640    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    641    eq(0, exc_exec(sdrcmd()))
    642    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    643    eq(0, exc_exec(sdrcmd()))
    644    nvim_command('normal! `A')
    645    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    646  end)
    647 
    648  it('uses last A mark with gt timestamp from file when reading', function()
    649    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    650    eq(0, exc_exec(sdrcmd()))
    651    wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    652    eq(0, exc_exec(sdrcmd()))
    653    nvim_command('normal! `A')
    654    eq('?', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    655  end)
    656 
    657  it('uses last A mark with gt timestamp from instance when writing', function()
    658    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    659    eq(0, exc_exec(sdrcmd()))
    660    wshada('\007\000\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    661    nvim_command('normal! `A')
    662    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    663    eq(0, exc_exec('wshada ' .. shada_fname))
    664    local found = {}
    665    for _, v in ipairs(read_shada_file(shada_fname)) do
    666      if v.type == 7 and v.value.f == mock_file_path .. '-' then
    667        local name = ('%c'):format(v.value.n)
    668        found[name] = (found[name] or 0) + 1
    669      end
    670    end
    671    eq({ ['0'] = 1, A = 1 }, found)
    672  end)
    673 
    674  it('uses last A mark with eq timestamp from instance when writing', function()
    675    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    676    eq(0, exc_exec(sdrcmd()))
    677    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    678    nvim_command('normal! `A')
    679    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    680    eq(0, exc_exec('wshada ' .. shada_fname))
    681    local found = {}
    682    for _, v in ipairs(read_shada_file(shada_fname)) do
    683      if v.type == 7 and v.value.f == mock_file_path .. '-' then
    684        local name = ('%c'):format(v.value.n)
    685        found[name] = (found[name] or 0) + 1
    686      end
    687    end
    688    eq({ ['0'] = 1, A = 1 }, found)
    689  end)
    690 
    691  it('uses last A mark with gt timestamp from file when writing', function()
    692    wshada('\007\001\018\131\162mX\195\161f\196\006' .. mock_file_path .. '-\161nA')
    693    eq(0, exc_exec(sdrcmd()))
    694    wshada('\007\002\018\131\162mX\195\161f\196\006' .. mock_file_path .. '?\161nA')
    695    nvim_command('normal! `A')
    696    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    697    eq(0, exc_exec('wshada ' .. shada_fname))
    698    local found = {}
    699    for _, v in ipairs(read_shada_file(shada_fname)) do
    700      if v.type == 7 then
    701        local name = ('%c'):format(v.value.n)
    702        local _t = found[name] or {}
    703        _t[v.value.f] = (_t[v.value.f] or 0) + 1
    704        found[name] = _t
    705      end
    706    end
    707    eq({ ['0'] = { [mock_file_path .. '-'] = 1 }, A = { [mock_file_path .. '?'] = 1 } }, found)
    708  end)
    709 
    710  it('uses last a mark with gt timestamp from instance when reading', function()
    711    nvim_command('edit ' .. mock_file_path .. '-')
    712    fn.setline(1, { '-', '?' })
    713    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    714    eq(0, exc_exec(sdrcmd()))
    715    wshada('\010\000\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    716    eq(0, exc_exec(sdrcmd()))
    717    nvim_command('normal! `a')
    718    eq('-', fn.getline('.'))
    719  end)
    720 
    721  it('uses last a mark with gt timestamp from file when reading with !', function()
    722    nvim_command('edit ' .. mock_file_path .. '-')
    723    fn.setline(1, { '-', '?' })
    724    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    725    eq(0, exc_exec(sdrcmd()))
    726    wshada('\010\000\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    727    eq(0, exc_exec(sdrcmd(true)))
    728    nvim_command('normal! `a')
    729    eq('?', fn.getline('.'))
    730  end)
    731 
    732  it('uses last a mark with eq timestamp from instance when reading', function()
    733    nvim_command('edit ' .. mock_file_path .. '-')
    734    fn.setline(1, { '-', '?' })
    735    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    736    eq(0, exc_exec(sdrcmd()))
    737    wshada('\010\001\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    738    eq(0, exc_exec(sdrcmd()))
    739    nvim_command('normal! `a')
    740    eq('-', fn.getline('.'))
    741  end)
    742 
    743  it('uses last a mark with gt timestamp from file when reading', function()
    744    nvim_command('edit ' .. mock_file_path .. '-')
    745    fn.setline(1, { '-', '?' })
    746    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    747    eq(0, exc_exec(sdrcmd()))
    748    wshada('\010\002\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    749    eq(0, exc_exec(sdrcmd()))
    750    nvim_command('normal! `a')
    751    eq('?', fn.getline('.'))
    752  end)
    753 
    754  it('uses last a mark with gt timestamp from instance when writing', function()
    755    nvim_command('edit ' .. mock_file_path .. '-')
    756    fn.setline(1, { '-', '?' })
    757    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    758    eq(0, exc_exec(sdrcmd()))
    759    wshada('\010\000\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    760    nvim_command('normal! `a')
    761    eq('-', fn.getline('.'))
    762    eq(0, exc_exec('wshada ' .. shada_fname))
    763    local found = 0
    764    for _, v in ipairs(read_shada_file(shada_fname)) do
    765      if
    766        v.type == 10
    767        and v.value.f == '' .. mock_file_path .. '-'
    768        and v.value.n == ('a'):byte()
    769      then
    770        eq(true, v.value.l == 1 or v.value.l == nil)
    771        found = found + 1
    772      end
    773    end
    774    eq(1, found)
    775  end)
    776 
    777  it('uses last a mark with eq timestamp from instance when writing', function()
    778    nvim_command('edit ' .. mock_file_path .. '-')
    779    fn.setline(1, { '-', '?' })
    780    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    781    eq(0, exc_exec(sdrcmd()))
    782    wshada('\010\001\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    783    nvim_command('normal! `a')
    784    eq('-', fn.getline('.'))
    785    eq(0, exc_exec('wshada ' .. shada_fname))
    786    local found = 0
    787    for _, v in ipairs(read_shada_file(shada_fname)) do
    788      if
    789        v.type == 10
    790        and v.value.f == '' .. mock_file_path .. '-'
    791        and v.value.n == ('a'):byte()
    792      then
    793        eq(true, v.value.l == 1 or v.value.l == nil)
    794        found = found + 1
    795      end
    796    end
    797    eq(1, found)
    798  end)
    799 
    800  it('uses last a mark with gt timestamp from file when writing', function()
    801    nvim_command('edit ' .. mock_file_path .. '-')
    802    fn.setline(1, { '-', '?' })
    803    wshada('\010\001\017\131\161l\001\161f\196\006' .. mock_file_path .. '-\161na')
    804    eq(0, exc_exec(sdrcmd()))
    805    wshada('\010\002\017\131\161l\002\161f\196\006' .. mock_file_path .. '-\161na')
    806    nvim_command('normal! `a')
    807    eq('-', fn.fnamemodify(api.nvim_buf_get_name(0), ':t'))
    808    eq(0, exc_exec('wshada ' .. shada_fname))
    809    local found = 0
    810    for _, v in ipairs(read_shada_file(shada_fname)) do
    811      if
    812        v.type == 10
    813        and v.value.f == '' .. mock_file_path .. '-'
    814        and v.value.n == ('a'):byte()
    815      then
    816        eq(2, v.value.l)
    817        found = found + 1
    818      end
    819    end
    820    eq(1, found)
    821  end)
    822 end)
    823 
    824 describe('ShaDa registers support code', function()
    825  before_each(reset)
    826  after_each(function()
    827    clear()
    828    os.remove(shada_fname)
    829  end)
    830 
    831  it('uses last a register with gt timestamp from instance when reading', function()
    832    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    833    eq(0, exc_exec(sdrcmd()))
    834    wshada('\005\000\015\131\161na\162rX\194\162rc\145\196\001?')
    835    eq(0, exc_exec(sdrcmd()))
    836    eq('-', fn.getreg('a'))
    837  end)
    838 
    839  it('uses last a register with gt timestamp from file when reading with !', function()
    840    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    841    eq(0, exc_exec(sdrcmd()))
    842    wshada('\005\000\015\131\161na\162rX\194\162rc\145\196\001?')
    843    eq(0, exc_exec(sdrcmd(true)))
    844    eq('?', fn.getreg('a'))
    845  end)
    846 
    847  it('uses last a register with eq timestamp from instance when reading', function()
    848    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    849    eq(0, exc_exec(sdrcmd()))
    850    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001?')
    851    eq(0, exc_exec(sdrcmd()))
    852    eq('-', fn.getreg('a'))
    853  end)
    854 
    855  it('uses last a register with gt timestamp from file when reading', function()
    856    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    857    eq(0, exc_exec(sdrcmd()))
    858    wshada('\005\002\015\131\161na\162rX\194\162rc\145\196\001?')
    859    eq(0, exc_exec(sdrcmd()))
    860    eq('?', fn.getreg('a'))
    861  end)
    862 
    863  it('uses last a register with gt timestamp from instance when writing', function()
    864    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    865    eq(0, exc_exec(sdrcmd()))
    866    wshada('\005\000\015\131\161na\162rX\194\162rc\145\196\001?')
    867    eq('-', fn.getreg('a'))
    868    eq(0, exc_exec('wshada ' .. shada_fname))
    869    local found = 0
    870    for _, v in ipairs(read_shada_file(shada_fname)) do
    871      if v.type == 5 and v.value.n == ('a'):byte() then
    872        eq({ '-' }, v.value.rc)
    873        found = found + 1
    874      end
    875    end
    876    eq(1, found)
    877  end)
    878 
    879  it('uses last a register with eq timestamp from instance when writing', function()
    880    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    881    eq(0, exc_exec(sdrcmd()))
    882    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001?')
    883    eq('-', fn.getreg('a'))
    884    eq(0, exc_exec('wshada ' .. shada_fname))
    885    local found = 0
    886    for _, v in ipairs(read_shada_file(shada_fname)) do
    887      if v.type == 5 and v.value.n == ('a'):byte() then
    888        eq({ '-' }, v.value.rc)
    889        found = found + 1
    890      end
    891    end
    892    eq(1, found)
    893  end)
    894 
    895  it('uses last a register with gt timestamp from file when writing', function()
    896    wshada('\005\001\015\131\161na\162rX\194\162rc\145\196\001-')
    897    eq(0, exc_exec(sdrcmd()))
    898    wshada('\005\002\015\131\161na\162rX\194\162rc\145\196\001?')
    899    eq('-', fn.getreg('a'))
    900    eq(0, exc_exec('wshada ' .. shada_fname))
    901    local found = 0
    902    for _, v in ipairs(read_shada_file(shada_fname)) do
    903      if v.type == 5 and v.value.n == ('a'):byte() then
    904        eq({ '?' }, v.value.rc)
    905        found = found + 1
    906      end
    907    end
    908    eq(1, found)
    909  end)
    910 end)
    911 
    912 describe('ShaDa jumps support code', function()
    913  before_each(reset)
    914  after_each(function()
    915    clear()
    916    os.remove(shada_fname)
    917  end)
    918 
    919  it('merges jumps when reading', function()
    920    wshada(
    921      '\008\001\018\131\162mX\195\161f\196\006'
    922        .. mock_file_path
    923        .. 'c\161l\002'
    924        .. '\008\004\018\131\162mX\195\161f\196\006'
    925        .. mock_file_path
    926        .. 'd\161l\002'
    927        .. '\008\007\018\131\162mX\195\161f\196\006'
    928        .. mock_file_path
    929        .. 'e\161l\002'
    930    )
    931    eq(0, exc_exec(sdrcmd()))
    932    wshada(
    933      '\008\001\018\131\162mX\195\161f\196\006'
    934        .. mock_file_path
    935        .. 'c\161l\002'
    936        .. '\008\004\018\131\162mX\195\161f\196\006'
    937        .. mock_file_path
    938        .. 'd\161l\003'
    939        .. '\008\007\018\131\162mX\195\161f\196\006'
    940        .. mock_file_path
    941        .. 'f\161l\002'
    942    )
    943    eq(0, exc_exec(sdrcmd()))
    944    eq('', api.nvim_buf_get_name(0))
    945    eq(
    946      ' jump line  col file/text\n'
    947        .. '   5     2    0 '
    948        .. mock_file_path
    949        .. 'c\n'
    950        .. '   4     2    0 '
    951        .. mock_file_path
    952        .. 'd\n'
    953        .. '   3     3    0 '
    954        .. mock_file_path
    955        .. 'd\n'
    956        .. '   2     2    0 '
    957        .. mock_file_path
    958        .. 'e\n'
    959        .. '   1     2    0 '
    960        .. mock_file_path
    961        .. 'f\n'
    962        .. '>',
    963      exec_capture('jumps')
    964    )
    965  end)
    966 
    967  it('merges jumps when writing', function()
    968    wshada(
    969      '\008\001\018\131\162mX\195\161f\196\006'
    970        .. mock_file_path
    971        .. 'c\161l\002'
    972        .. '\008\004\018\131\162mX\195\161f\196\006'
    973        .. mock_file_path
    974        .. 'd\161l\002'
    975        .. '\008\007\018\131\162mX\195\161f\196\006'
    976        .. mock_file_path
    977        .. 'e\161l\002'
    978    )
    979    eq(0, exc_exec(sdrcmd()))
    980    wshada(
    981      '\008\001\018\131\162mX\195\161f\196\006'
    982        .. mock_file_path
    983        .. 'c\161l\002'
    984        .. '\008\004\018\131\162mX\195\161f\196\006'
    985        .. mock_file_path
    986        .. 'd\161l\003'
    987        .. '\008\007\018\131\162mX\195\161f\196\006'
    988        .. mock_file_path
    989        .. 'f\161l\002'
    990    )
    991    eq(0, exc_exec('wshada ' .. shada_fname))
    992    local jumps = {
    993      { file = '' .. mock_file_path .. 'c', line = 2 },
    994      { file = '' .. mock_file_path .. 'd', line = 2 },
    995      { file = '' .. mock_file_path .. 'd', line = 3 },
    996      { file = '' .. mock_file_path .. 'e', line = 2 },
    997      { file = '' .. mock_file_path .. 'f', line = 2 },
    998    }
    999    local found = 0
   1000    for _, v in ipairs(read_shada_file(shada_fname)) do
   1001      if v.type == 8 then
   1002        found = found + 1
   1003        eq(jumps[found].file, v.value.f)
   1004        eq(jumps[found].line, v.value.l)
   1005      end
   1006    end
   1007    eq(#jumps, found)
   1008  end)
   1009 
   1010  it('merges JUMPLISTSIZE jumps when writing', function()
   1011    local jumps = {}
   1012    local shada = ''
   1013    for i = 1, 100 do
   1014      shada = shada
   1015        .. ('\008%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'):format(i, i)
   1016      jumps[i] = { file = '' .. mock_file_path .. 'c', line = i }
   1017    end
   1018    wshada(shada)
   1019    eq(0, exc_exec(sdrcmd()))
   1020    shada = ''
   1021    for i = 1, 101 do
   1022      local _t = i * 2
   1023      shada = shada
   1024        .. ('\008\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format(
   1025          _t,
   1026          _t
   1027        )
   1028      jumps[(_t > #jumps + 1) and (#jumps + 1) or _t] =
   1029        { file = '' .. mock_file_path .. 'c', line = _t }
   1030    end
   1031    wshada(shada)
   1032    eq(0, exc_exec('wshada ' .. shada_fname))
   1033    local shift = #jumps - 100
   1034    for i = 1, 100 do
   1035      jumps[i] = jumps[i + shift]
   1036    end
   1037    local found = 0
   1038    for _, v in ipairs(read_shada_file(shada_fname)) do
   1039      if v.type == 8 then
   1040        found = found + 1
   1041        eq(jumps[found].file, v.value.f)
   1042        eq(jumps[found].line, v.value.l)
   1043      end
   1044    end
   1045    eq(100, found)
   1046  end)
   1047 end)
   1048 
   1049 describe('ShaDa changes support code', function()
   1050  before_each(reset)
   1051  after_each(function()
   1052    clear()
   1053    os.remove(shada_fname)
   1054  end)
   1055 
   1056  it('merges changes when reading', function()
   1057    nvim_command('edit ' .. mock_file_path .. 'c')
   1058    nvim_command('keepjumps call setline(1, range(7))')
   1059    wshada(
   1060      '\011\001\018\131\162mX\195\161f\196\006'
   1061        .. mock_file_path
   1062        .. 'c\161l\001'
   1063        .. '\011\004\018\131\162mX\195\161f\196\006'
   1064        .. mock_file_path
   1065        .. 'c\161l\002'
   1066        .. '\011\007\018\131\162mX\195\161f\196\006'
   1067        .. mock_file_path
   1068        .. 'c\161l\003'
   1069    )
   1070    eq(0, exc_exec(sdrcmd()))
   1071    wshada(
   1072      '\011\001\018\131\162mX\194\161f\196\006'
   1073        .. mock_file_path
   1074        .. 'c\161l\001'
   1075        .. '\011\004\018\131\162mX\195\161f\196\006'
   1076        .. mock_file_path
   1077        .. 'c\161l\005'
   1078        .. '\011\008\018\131\162mX\195\161f\196\006'
   1079        .. mock_file_path
   1080        .. 'c\161l\004'
   1081    )
   1082    eq(0, exc_exec(sdrcmd()))
   1083    eq(
   1084      'change line  col text\n'
   1085        .. '    5     1    0 0\n'
   1086        .. '    4     2    0 1\n'
   1087        .. '    3     5    0 4\n'
   1088        .. '    2     3    0 2\n'
   1089        .. '    1     4    0 3\n'
   1090        .. '>',
   1091      exec_capture('changes')
   1092    )
   1093  end)
   1094 
   1095  it('merges changes when writing', function()
   1096    nvim_command('edit ' .. mock_file_path .. 'c')
   1097    nvim_command('keepjumps call setline(1, range(7))')
   1098    wshada(
   1099      '\011\001\018\131\162mX\195\161f\196\006'
   1100        .. mock_file_path
   1101        .. 'c\161l\001'
   1102        .. '\011\004\018\131\162mX\195\161f\196\006'
   1103        .. mock_file_path
   1104        .. 'c\161l\002'
   1105        .. '\011\007\018\131\162mX\195\161f\196\006'
   1106        .. mock_file_path
   1107        .. 'c\161l\003'
   1108    )
   1109    eq(0, exc_exec(sdrcmd()))
   1110    wshada(
   1111      '\011\001\018\131\162mX\194\161f\196\006'
   1112        .. mock_file_path
   1113        .. 'c\161l\001'
   1114        .. '\011\004\018\131\162mX\195\161f\196\006'
   1115        .. mock_file_path
   1116        .. 'c\161l\005'
   1117        .. '\011\008\018\131\162mX\195\161f\196\006'
   1118        .. mock_file_path
   1119        .. 'c\161l\004'
   1120    )
   1121    eq(0, exc_exec('wshada ' .. shada_fname))
   1122    local changes = {
   1123      { line = 1 },
   1124      { line = 2 },
   1125      { line = 5 },
   1126      { line = 3 },
   1127      { line = 4 },
   1128    }
   1129    local found = 0
   1130    for _, v in ipairs(read_shada_file(shada_fname)) do
   1131      if v.type == 11 and v.value.f == '' .. mock_file_path .. 'c' then
   1132        found = found + 1
   1133        eq(changes[found].line, v.value.l or 1)
   1134      end
   1135    end
   1136    eq(#changes, found)
   1137  end)
   1138 
   1139  it('merges JUMPLISTSIZE changes when writing', function()
   1140    nvim_command('edit ' .. mock_file_path .. 'c')
   1141    nvim_command('keepjumps call setline(1, range(202))')
   1142    local changes = {}
   1143    local shada = ''
   1144    for i = 1, 100 do
   1145      shada = shada
   1146        .. ('\011%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'):format(i, i)
   1147      changes[i] = { line = i }
   1148    end
   1149    wshada(shada)
   1150    eq(0, exc_exec(sdrcmd()))
   1151    shada = ''
   1152    for i = 1, 101 do
   1153      local _t = i * 2
   1154      shada = shada
   1155        .. ('\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format(
   1156          _t,
   1157          _t
   1158        )
   1159      changes[(_t > #changes + 1) and (#changes + 1) or _t] = { line = _t }
   1160    end
   1161    wshada(shada)
   1162    eq(0, exc_exec('wshada ' .. shada_fname))
   1163    local shift = #changes - 100
   1164    for i = 1, 100 do
   1165      changes[i] = changes[i + shift]
   1166    end
   1167    local found = 0
   1168    for _, v in ipairs(read_shada_file(shada_fname)) do
   1169      if v.type == 11 and v.value.f == '' .. mock_file_path .. 'c' then
   1170        found = found + 1
   1171        eq(changes[found].line, v.value.l)
   1172      end
   1173    end
   1174    eq(100, found)
   1175  end)
   1176 
   1177  it('merges JUMPLISTSIZE changes when writing, with new items between old', function()
   1178    nvim_command('edit ' .. mock_file_path .. 'c')
   1179    nvim_command('keepjumps call setline(1, range(202))')
   1180    local shada = ''
   1181    for i = 1, 101 do
   1182      local _t = i * 2
   1183      shada = shada
   1184        .. ('\011\204%c\019\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l\204%c'):format(
   1185          _t,
   1186          _t
   1187        )
   1188    end
   1189    wshada(shada)
   1190    eq(0, exc_exec(sdrcmd()))
   1191    shada = ''
   1192    for i = 1, 100 do
   1193      shada = shada
   1194        .. ('\011%c\018\131\162mX\195\161f\196\006' .. mock_file_path .. 'c\161l%c'):format(i, i)
   1195    end
   1196    local changes = {}
   1197    for i = 1, 100 do
   1198      changes[i] = { line = i }
   1199    end
   1200    for i = 1, 101 do
   1201      local _t = i * 2
   1202      changes[(_t > #changes + 1) and (#changes + 1) or _t] = { line = _t }
   1203    end
   1204    wshada(shada)
   1205    eq(0, exc_exec('wshada ' .. shada_fname))
   1206    local shift = #changes - 100
   1207    for i = 1, 100 do
   1208      changes[i] = changes[i + shift]
   1209    end
   1210    local found = 0
   1211    for _, v in ipairs(read_shada_file(shada_fname)) do
   1212      if v.type == 11 and v.value.f == '' .. mock_file_path .. 'c' then
   1213        found = found + 1
   1214        eq(changes[found].line, v.value.l)
   1215      end
   1216    end
   1217    eq(100, found)
   1218  end)
   1219 end)