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