1" Tests for diff mode
2source shared.vim
3source screendump.vim
4source check.vim
5
6func Test_diff_fold_sync()
7  enew!
8  let g:update_count = 0
9  au DiffUpdated * let g:update_count += 1
10
11  let l = range(50)
12  call setline(1, l)
13  diffthis
14  let winone = win_getid()
15  new
16  let l[25] = 'diff'
17  call setline(1, l)
18  diffthis
19  let wintwo = win_getid()
20  " line 15 is inside the closed fold
21  call assert_equal(19, foldclosedend(10))
22  call win_gotoid(winone)
23  call assert_equal(19, foldclosedend(10))
24  " open the fold
25  normal zv
26  call assert_equal(-1, foldclosedend(10))
27  " fold in other window must have opened too
28  call win_gotoid(wintwo)
29  call assert_equal(-1, foldclosedend(10))
30
31  " cursor position is in sync
32  normal 23G
33  call win_gotoid(winone)
34  call assert_equal(23, getcurpos()[1])
35
36  call assert_equal(1, g:update_count)
37  au! DiffUpdated
38
39  windo diffoff
40  close!
41  set nomodified
42endfunc
43
44func Test_vert_split()
45  set diffopt=filler
46  call Common_vert_split()
47  set diffopt&
48endfunc
49
50func Test_vert_split_internal()
51  set diffopt=internal,filler
52  call Common_vert_split()
53  set diffopt&
54endfunc
55
56func Common_vert_split()
57  " Disable the title to avoid xterm keeping the wrong one.
58  set notitle noicon
59  new
60  let l = ['1 aa', '2 bb', '3 cc', '4 dd', '5 ee']
61  call setline(1, l)
62  w! Xtest
63  normal dd
64  $
65  put
66  normal kkrXoxxx
67  w! Xtest2
68  file Nop
69  normal ggoyyyjjjozzzz
70  set foldmethod=marker foldcolumn=4
71  call assert_equal(0, &diff)
72  call assert_equal('marker', &foldmethod)
73  call assert_equal(4, &foldcolumn)
74  call assert_equal(0, &scrollbind)
75  call assert_equal(0, &cursorbind)
76  call assert_equal(1, &wrap)
77
78  vert diffsplit Xtest
79  vert diffsplit Xtest2
80  call assert_equal(1, &diff)
81  call assert_equal('diff', &foldmethod)
82  call assert_equal(2, &foldcolumn)
83  call assert_equal(1, &scrollbind)
84  call assert_equal(1, &cursorbind)
85  call assert_equal(0, &wrap)
86
87  let diff_fdm = &fdm
88  let diff_fdc = &fdc
89  " repeat entering diff mode here to see if this saves the wrong settings
90  diffthis
91  " jump to second window for a moment to have filler line appear at start of
92  " first window
93  wincmd w
94  normal gg
95  wincmd p
96  normal gg
97  call assert_equal(2, winline())
98  normal j
99  call assert_equal(4, winline())
100  normal j
101  call assert_equal(5, winline())
102  normal j
103  call assert_equal(6, winline())
104  normal j
105  call assert_equal(8, winline())
106  normal j
107  call assert_equal(9, winline())
108
109  wincmd w
110  normal gg
111  call assert_equal(1, winline())
112  normal j
113  call assert_equal(2, winline())
114  normal j
115  call assert_equal(4, winline())
116  normal j
117  call assert_equal(5, winline())
118  normal j
119  call assert_equal(8, winline())
120
121  wincmd w
122  normal gg
123  call assert_equal(2, winline())
124  normal j
125  call assert_equal(3, winline())
126  normal j
127  call assert_equal(4, winline())
128  normal j
129  call assert_equal(5, winline())
130  normal j
131  call assert_equal(6, winline())
132  normal j
133  call assert_equal(7, winline())
134  normal j
135  call assert_equal(8, winline())
136
137  " Test diffoff
138  diffoff!
139  1wincmd 2
140  let &diff = 1
141  let &fdm = diff_fdm
142  let &fdc = diff_fdc
143  4wincmd w
144  diffoff!
145  1wincmd w
146  call assert_equal(0, &diff)
147  call assert_equal('marker', &foldmethod)
148  call assert_equal(4, &foldcolumn)
149  call assert_equal(0, &scrollbind)
150  call assert_equal(0, &cursorbind)
151  call assert_equal(1, &wrap)
152
153  wincmd w
154  call assert_equal(0, &diff)
155  call assert_equal('marker', &foldmethod)
156  call assert_equal(4, &foldcolumn)
157  call assert_equal(0, &scrollbind)
158  call assert_equal(0, &cursorbind)
159  call assert_equal(1, &wrap)
160
161  wincmd w
162  call assert_equal(0, &diff)
163  call assert_equal('marker', &foldmethod)
164  call assert_equal(4, &foldcolumn)
165  call assert_equal(0, &scrollbind)
166  call assert_equal(0, &cursorbind)
167  call assert_equal(1, &wrap)
168
169  call delete('Xtest')
170  call delete('Xtest2')
171  windo bw!
172endfunc
173
174func Test_filler_lines()
175  " Test that diffing shows correct filler lines
176  enew!
177  put =range(4,10)
178  1d _
179  vnew
180  put =range(1,10)
181  1d _
182  windo diffthis
183  wincmd h
184  call assert_equal(1, line('w0'))
185  unlet! diff_fdm diff_fdc
186  windo diffoff
187  bwipe!
188  enew!
189endfunc
190
191func Test_diffget_diffput()
192  enew!
193  let l = range(50)
194  call setline(1, l)
195  call assert_fails('diffget', 'E99:')
196  diffthis
197  call assert_fails('diffget', 'E100:')
198  new
199  let l[10] = 'one'
200  let l[20] = 'two'
201  let l[30] = 'three'
202  let l[40] = 'four'
203  call setline(1, l)
204  diffthis
205  call assert_equal('one', getline(11))
206  11diffget
207  call assert_equal('10', getline(11))
208  21diffput
209  wincmd w
210  call assert_equal('two', getline(21))
211  normal 31Gdo
212  call assert_equal('three', getline(31))
213  call assert_equal('40', getline(41))
214  normal 41Gdp
215  wincmd w
216  call assert_equal('40', getline(41))
217  new
218  diffthis
219  call assert_fails('diffget', 'E101:')
220
221  windo diffoff
222  %bwipe!
223endfunc
224
225" Test putting two changes from one buffer to another
226func Test_diffput_two()
227  new a
228  let win_a = win_getid()
229  call setline(1, range(1, 10))
230  diffthis
231  new b
232  let win_b = win_getid()
233  call setline(1, range(1, 10))
234  8del
235  5del
236  diffthis
237  call win_gotoid(win_a)
238  %diffput
239  call win_gotoid(win_b)
240  call assert_equal(map(range(1, 10), 'string(v:val)'), getline(1, '$'))
241  bwipe! a
242  bwipe! b
243endfunc
244
245" :diffput and :diffget completes names of buffers which
246" are in diff mode and which are different then current buffer.
247" No completion when the current window is not in diff mode.
248func Test_diffget_diffput_completion()
249  e            Xdiff1 | diffthis
250  botright new Xdiff2
251  botright new Xdiff3 | split | diffthis
252  botright new Xdiff4 | diffthis
253
254  wincmd t
255  call assert_equal('Xdiff1', bufname('%'))
256  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
257  call assert_equal('"diffput Xdiff3 Xdiff4', @:)
258  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
259  call assert_equal('"diffget Xdiff3 Xdiff4', @:)
260  call assert_equal(['Xdiff3', 'Xdiff4'], getcompletion('', 'diff_buffer'))
261
262  " Xdiff2 is not in diff mode, so no completion for :diffput, :diffget
263  wincmd j
264  call assert_equal('Xdiff2', bufname('%'))
265  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
266  call assert_equal('"diffput ', @:)
267  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
268  call assert_equal('"diffget ', @:)
269  call assert_equal([], getcompletion('', 'diff_buffer'))
270
271  " Xdiff3 is split in 2 windows, only the top one is in diff mode.
272  " So completion of :diffput :diffget only happens in the top window.
273  wincmd j
274  call assert_equal('Xdiff3', bufname('%'))
275  call assert_equal(1, &diff)
276  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
277  call assert_equal('"diffput Xdiff1 Xdiff4', @:)
278  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
279  call assert_equal('"diffget Xdiff1 Xdiff4', @:)
280  call assert_equal(['Xdiff1', 'Xdiff4'], getcompletion('', 'diff_buffer'))
281
282  wincmd j
283  call assert_equal('Xdiff3', bufname('%'))
284  call assert_equal(0, &diff)
285  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
286  call assert_equal('"diffput ', @:)
287  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
288  call assert_equal('"diffget ', @:)
289  call assert_equal([], getcompletion('', 'diff_buffer'))
290
291  wincmd j
292  call assert_equal('Xdiff4', bufname('%'))
293  call feedkeys(":diffput \<C-A>\<C-B>\"\<CR>", 'tx')
294  call assert_equal('"diffput Xdiff1 Xdiff3', @:)
295  call feedkeys(":diffget \<C-A>\<C-B>\"\<CR>", 'tx')
296  call assert_equal('"diffget Xdiff1 Xdiff3', @:)
297  call assert_equal(['Xdiff1', 'Xdiff3'], getcompletion('', 'diff_buffer'))
298
299  %bwipe
300endfunc
301
302func Test_dp_do_buffer()
303  e! one
304  let bn1=bufnr('%')
305  let l = range(60)
306  call setline(1, l)
307  diffthis
308
309  new two
310  let l[10] = 'one'
311  let l[20] = 'two'
312  let l[30] = 'three'
313  let l[40] = 'four'
314  let l[50] = 'five'
315  call setline(1, l)
316  diffthis
317
318  " dp and do with invalid buffer number.
319  11
320  call assert_fails('norm 99999dp', 'E102:')
321  call assert_fails('norm 99999do', 'E102:')
322  call assert_fails('diffput non_existing_buffer', 'E94:')
323  call assert_fails('diffget non_existing_buffer', 'E94:')
324
325  " dp and do with valid buffer number.
326  call assert_equal('one', getline('.'))
327  exe 'norm ' . bn1 . 'do'
328  call assert_equal('10', getline('.'))
329  21
330  call assert_equal('two', getline('.'))
331  diffget one
332  call assert_equal('20', getline('.'))
333
334  31
335  exe 'norm ' . bn1 . 'dp'
336  41
337  diffput one
338  wincmd w
339  31
340  call assert_equal('three', getline('.'))
341  41
342  call assert_equal('four', getline('.'))
343
344  " dp and do with buffer number which is not in diff mode.
345  new not_in_diff_mode
346  let bn3=bufnr('%')
347  wincmd w
348  51
349  call assert_fails('exe "norm" . bn3 . "dp"', 'E103:')
350  call assert_fails('exe "norm" . bn3 . "do"', 'E103:')
351  call assert_fails('diffput not_in_diff_mode', 'E94:')
352  call assert_fails('diffget not_in_diff_mode', 'E94:')
353
354  windo diffoff
355  %bwipe!
356endfunc
357
358func Test_do_lastline()
359  e! one
360  call setline(1, ['1','2','3','4','5','6'])
361  diffthis
362
363  new two
364  call setline(1, ['2','4','5'])
365  diffthis
366
367  1
368  norm dp]c
369  norm dp]c
370  wincmd w
371  call assert_equal(4, line('$'))
372  norm G
373  norm do
374  call assert_equal(3, line('$'))
375
376  windo diffoff
377  %bwipe!
378endfunc
379
380func Test_diffoff()
381  enew!
382  call setline(1, ['Two', 'Three'])
383  redraw
384  let normattr = screenattr(1, 1)
385  diffthis
386  botright vert new
387  call setline(1, ['One', '', 'Two', 'Three'])
388  diffthis
389  redraw
390  call assert_notequal(normattr, 1->screenattr(1))
391  diffoff!
392  redraw
393  call assert_equal(normattr, screenattr(1, 1))
394  bwipe!
395  bwipe!
396endfunc
397
398func Common_icase_test()
399  edit one
400  call setline(1, ['One', 'Two', 'Three', 'Four', 'Fi#ve'])
401  redraw
402  let normattr = screenattr(1, 1)
403  diffthis
404
405  botright vert new two
406  call setline(1, ['one', 'TWO', 'Three ', 'Four', 'fI=VE'])
407  diffthis
408
409  redraw
410  call assert_equal(normattr, screenattr(1, 1))
411  call assert_equal(normattr, screenattr(2, 1))
412  call assert_notequal(normattr, screenattr(3, 1))
413  call assert_equal(normattr, screenattr(4, 1))
414
415  let dtextattr = screenattr(5, 3)
416  call assert_notequal(dtextattr, screenattr(5, 1))
417  call assert_notequal(dtextattr, screenattr(5, 5))
418
419  diffoff!
420  %bwipe!
421endfunc
422
423func Test_diffopt_icase()
424  set diffopt=icase,foldcolumn:0
425  call Common_icase_test()
426  set diffopt&
427endfunc
428
429func Test_diffopt_icase_internal()
430  set diffopt=icase,foldcolumn:0,internal
431  call Common_icase_test()
432  set diffopt&
433endfunc
434
435func Common_iwhite_test()
436  edit one
437  " Difference in trailing spaces and amount of spaces should be ignored,
438  " but not other space differences.
439  call setline(1, ["One \t", 'Two', 'Three', 'one two', 'one two', 'Four'])
440  redraw
441  let normattr = screenattr(1, 1)
442  diffthis
443
444  botright vert new two
445  call setline(1, ["One\t ", "Two\t ", 'Three', 'one   two', 'onetwo', ' Four'])
446  diffthis
447
448  redraw
449  call assert_equal(normattr, screenattr(1, 1))
450  call assert_equal(normattr, screenattr(2, 1))
451  call assert_equal(normattr, screenattr(3, 1))
452  call assert_equal(normattr, screenattr(4, 1))
453  call assert_notequal(normattr, screenattr(5, 1))
454  call assert_notequal(normattr, screenattr(6, 1))
455
456  diffoff!
457  %bwipe!
458endfunc
459
460func Test_diffopt_iwhite()
461  set diffopt=iwhite,foldcolumn:0
462  call Common_iwhite_test()
463  set diffopt&
464endfunc
465
466func Test_diffopt_iwhite_internal()
467  set diffopt=internal,iwhite,foldcolumn:0
468  call Common_iwhite_test()
469  set diffopt&
470endfunc
471
472func Test_diffopt_context()
473  enew!
474  call setline(1, ['1', '2', '3', '4', '5', '6', '7'])
475  diffthis
476  new
477  call setline(1, ['1', '2', '3', '4', '5x', '6', '7'])
478  diffthis
479
480  set diffopt=context:2
481  call assert_equal('+--  2 lines: 1', foldtextresult(1))
482  set diffopt=internal,context:2
483  call assert_equal('+--  2 lines: 1', foldtextresult(1))
484
485  set diffopt=context:1
486  call assert_equal('+--  3 lines: 1', foldtextresult(1))
487  set diffopt=internal,context:1
488  call assert_equal('+--  3 lines: 1', foldtextresult(1))
489
490  diffoff!
491  %bwipe!
492  set diffopt&
493endfunc
494
495func Test_diffopt_horizontal()
496  set diffopt=internal,horizontal
497  diffsplit
498
499  call assert_equal(&columns, winwidth(1))
500  call assert_equal(&columns, winwidth(2))
501  call assert_equal(&lines, winheight(1) + winheight(2) + 3)
502  call assert_inrange(0, 1, winheight(1) - winheight(2))
503
504  set diffopt&
505  diffoff!
506  %bwipe
507endfunc
508
509func Test_diffopt_vertical()
510  set diffopt=internal,vertical
511  diffsplit
512
513  call assert_equal(&lines - 2, winheight(1))
514  call assert_equal(&lines - 2, winheight(2))
515  call assert_equal(&columns, winwidth(1) + winwidth(2) + 1)
516  call assert_inrange(0, 1, winwidth(1) - winwidth(2))
517
518  set diffopt&
519  diffoff!
520  %bwipe
521endfunc
522
523func Test_diffopt_hiddenoff()
524  set diffopt=internal,filler,foldcolumn:0,hiddenoff
525  e! one
526  call setline(1, ['Two', 'Three'])
527  redraw
528  let normattr = screenattr(1, 1)
529  diffthis
530  botright vert new two
531  call setline(1, ['One', 'Four'])
532  diffthis
533  redraw
534  call assert_notequal(normattr, screenattr(1, 1))
535  set hidden
536  close
537  redraw
538  " should not diffing with hidden buffer two while 'hiddenoff' is enabled
539  call assert_equal(normattr, screenattr(1, 1))
540
541  bwipe!
542  bwipe!
543  set hidden& diffopt&
544endfunc
545
546func Test_diffoff_hidden()
547  set diffopt=internal,filler,foldcolumn:0
548  e! one
549  call setline(1, ['Two', 'Three'])
550  redraw
551  let normattr = screenattr(1, 1)
552  diffthis
553  botright vert new two
554  call setline(1, ['One', 'Four'])
555  diffthis
556  redraw
557  call assert_notequal(normattr, screenattr(1, 1))
558  set hidden
559  close
560  redraw
561  " diffing with hidden buffer two
562  call assert_notequal(normattr, screenattr(1, 1))
563  diffoff
564  redraw
565  call assert_equal(normattr, screenattr(1, 1))
566  diffthis
567  redraw
568  " still diffing with hidden buffer two
569  call assert_notequal(normattr, screenattr(1, 1))
570  diffoff!
571  redraw
572  call assert_equal(normattr, screenattr(1, 1))
573  diffthis
574  redraw
575  " no longer diffing with hidden buffer two
576  call assert_equal(normattr, screenattr(1, 1))
577
578  bwipe!
579  bwipe!
580  set hidden& diffopt&
581endfunc
582
583func Test_setting_cursor()
584  new Xtest1
585  put =range(1,90)
586  wq
587  new Xtest2
588  put =range(1,100)
589  wq
590
591  tabe Xtest2
592  $
593  diffsp Xtest1
594  tabclose
595
596  call delete('Xtest1')
597  call delete('Xtest2')
598endfunc
599
600func Test_diff_move_to()
601  new
602  call setline(1, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
603  diffthis
604  vnew
605  call setline(1, [1, '2x', 3, 4, 4, 5, '6x', 7, '8x', 9, '10x'])
606  diffthis
607  norm ]c
608  call assert_equal(2, line('.'))
609  norm 3]c
610  call assert_equal(9, line('.'))
611  norm 10]c
612  call assert_equal(11, line('.'))
613  norm [c
614  call assert_equal(9, line('.'))
615  norm 2[c
616  call assert_equal(5, line('.'))
617  norm 10[c
618  call assert_equal(2, line('.'))
619  %bwipe!
620endfunc
621
622func Test_diffexpr()
623  if !executable('diff')
624    return
625  endif
626
627  func DiffExpr()
628    " Prepent some text to check diff type detection
629    call writefile(['warning', '  message'], v:fname_out)
630    silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>>' . v:fname_out
631  endfunc
632  set diffexpr=DiffExpr()
633  set diffopt=foldcolumn:0
634
635  enew!
636  call setline(1, ['one', 'two', 'three'])
637  redraw
638  let normattr = screenattr(1, 1)
639  diffthis
640
641  botright vert new
642  call setline(1, ['one', 'two', 'three.'])
643  diffthis
644
645  redraw
646  call assert_equal(normattr, screenattr(1, 1))
647  call assert_equal(normattr, screenattr(2, 1))
648  call assert_notequal(normattr, screenattr(3, 1))
649
650  diffoff!
651  %bwipe!
652  set diffexpr& diffopt&
653endfunc
654
655func Test_diffpatch()
656  " The patch program on MS-Windows may fail or hang.
657  if !executable('patch') || !has('unix')
658    return
659  endif
660  new
661  insert
662***************
663*** 1,3 ****
664  1
665! 2
666  3
667--- 1,4 ----
668  1
669! 2x
670  3
671+ 4
672.
673  saveas! Xpatch
674  bwipe!
675  new
676  call assert_fails('diffpatch Xpatch', 'E816:')
677
678  for name in ['Xpatch', 'Xpatch$HOME', 'Xpa''tch']
679    call setline(1, ['1', '2', '3'])
680    if name != 'Xpatch'
681      call rename('Xpatch', name)
682    endif
683    exe 'diffpatch ' . escape(name, '$')
684    call assert_equal(['1', '2x', '3', '4'], getline(1, '$'))
685    if name != 'Xpatch'
686      call rename(name, 'Xpatch')
687    endif
688    bwipe!
689  endfor
690
691  call delete('Xpatch')
692  bwipe!
693endfunc
694
695func Test_diff_too_many_buffers()
696  for i in range(1, 8)
697    exe "new Xtest" . i
698    diffthis
699  endfor
700  new Xtest9
701  call assert_fails('diffthis', 'E96:')
702  %bwipe!
703endfunc
704
705func Test_diff_nomodifiable()
706  new
707  call setline(1, [1, 2, 3, 4])
708  setl nomodifiable
709  diffthis
710  vnew
711  call setline(1, ['1x', 2, 3, 3, 4])
712  diffthis
713  call assert_fails('norm dp', 'E793:')
714  setl nomodifiable
715  call assert_fails('norm do', 'E21:')
716  %bwipe!
717endfunc
718
719func Test_diff_hlID()
720  new
721  call setline(1, [1, 2, 3])
722  diffthis
723  vnew
724  call setline(1, ['1x', 2, 'x', 3])
725  diffthis
726  redraw
727
728  call diff_hlID(-1, 1)->synIDattr("name")->assert_equal("")
729
730  call diff_hlID(1, 1)->synIDattr("name")->assert_equal("DiffChange")
731  call diff_hlID(1, 2)->synIDattr("name")->assert_equal("DiffText")
732  call diff_hlID(2, 1)->synIDattr("name")->assert_equal("")
733  call diff_hlID(3, 1)->synIDattr("name")->assert_equal("DiffAdd")
734  eval 4->diff_hlID(1)->synIDattr("name")->assert_equal("")
735
736  wincmd w
737  call assert_equal(synIDattr(diff_hlID(1, 1), "name"), "DiffChange")
738  call assert_equal(synIDattr(diff_hlID(2, 1), "name"), "")
739  call assert_equal(synIDattr(diff_hlID(3, 1), "name"), "")
740
741  %bwipe!
742endfunc
743
744func Test_diff_filler()
745  new
746  call setline(1, [1, 2, 3, 'x', 4])
747  diffthis
748  vnew
749  call setline(1, [1, 2, 'y', 'y', 3, 4])
750  diffthis
751  redraw
752
753  call assert_equal([0, 0, 0, 0, 0, 0, 0, 1, 0], map(range(-1, 7), 'v:val->diff_filler()'))
754  wincmd w
755  call assert_equal([0, 0, 0, 0, 2, 0, 0, 0], map(range(-1, 6), 'diff_filler(v:val)'))
756
757  %bwipe!
758endfunc
759
760func Test_diff_lastline()
761  enew!
762  only!
763  call setline(1, ['This is a ', 'line with five ', 'rows'])
764  diffthis
765  botright vert new
766  call setline(1, ['This is', 'a line with ', 'four rows'])
767  diffthis
768  1
769  call feedkeys("Je a\<CR>", 'tx')
770  call feedkeys("Je a\<CR>", 'tx')
771  let w1lines = winline()
772  wincmd w
773  $
774  let w2lines = winline()
775  call assert_equal(w2lines, w1lines)
776  bwipe!
777  bwipe!
778endfunc
779
780func WriteDiffFiles(buf, list1, list2)
781  call writefile(a:list1, 'Xfile1')
782  call writefile(a:list2, 'Xfile2')
783  if a:buf
784    call term_sendkeys(a:buf, ":checktime\<CR>")
785  endif
786endfunc
787
788" Verify a screendump with both the internal and external diff.
789func VerifyBoth(buf, dumpfile, extra)
790  " trailing : for leaving the cursor on the command line
791  for cmd in [":set diffopt=filler" . a:extra . "\<CR>:", ":set diffopt+=internal\<CR>:"]
792    call term_sendkeys(a:buf, cmd)
793    if VerifyScreenDump(a:buf, a:dumpfile, {}, cmd =~ 'internal' ? 'internal' : 'external')
794      break " don't let the next iteration overwrite the "failed" file.
795    endif
796  endfor
797endfunc
798
799" Verify a screendump with the internal diff only.
800func VerifyInternal(buf, dumpfile, extra)
801  call term_sendkeys(a:buf, ":diffupdate!\<CR>")
802  " trailing : for leaving the cursor on the command line
803  call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
804  call TermWait(a:buf)
805  call VerifyScreenDump(a:buf, a:dumpfile, {})
806endfunc
807
808func Test_diff_screen()
809  CheckScreendump
810  CheckFeature menu
811
812  " clean up already existing swap files, just in case
813  call delete('.Xfile1.swp')
814  call delete('.Xfile2.swp')
815
816  " Test 1: Add a line in beginning of file 2
817  call WriteDiffFiles(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
818  let buf = RunVimInTerminal('-d Xfile1 Xfile2', {})
819  " Set autoread mode, so that Vim won't complain once we re-write the test
820  " files
821  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
822
823  call VerifyBoth(buf, 'Test_diff_01', '')
824
825  " Test 2: Add a line in beginning of file 1
826  call WriteDiffFiles(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
827  call VerifyBoth(buf, 'Test_diff_02', '')
828
829  " Test 3: Add a line at the end of file 2
830  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
831  call VerifyBoth(buf, 'Test_diff_03', '')
832
833  " Test 4: Add a line at the end of file 1
834  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
835  call VerifyBoth(buf, 'Test_diff_04', '')
836
837  " Test 5: Add a line in the middle of file 2, remove on at the end of file 1
838  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10])
839  call VerifyBoth(buf, 'Test_diff_05', '')
840
841  " Test 6: Add a line in the middle of file 1, remove on at the end of file 2
842  call WriteDiffFiles(buf, [1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
843  call VerifyBoth(buf, 'Test_diff_06', '')
844
845  " Variants on test 6 with different context settings
846  call term_sendkeys(buf, ":set diffopt+=context:2\<cr>")
847  call VerifyScreenDump(buf, 'Test_diff_06.2', {})
848  call term_sendkeys(buf, ":set diffopt-=context:2\<cr>")
849  call term_sendkeys(buf, ":set diffopt+=context:1\<cr>")
850  call VerifyScreenDump(buf, 'Test_diff_06.1', {})
851  call term_sendkeys(buf, ":set diffopt-=context:1\<cr>")
852  call term_sendkeys(buf, ":set diffopt+=context:0\<cr>")
853  call VerifyScreenDump(buf, 'Test_diff_06.0', {})
854  call term_sendkeys(buf, ":set diffopt-=context:0\<cr>")
855
856  " Test 7 - 9: Test normal/patience/histogram diff algorithm
857  call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
858      \ '    int i;', '    for(i = 0; i < 10; i++)', '    {', '        printf("Your answer is: ");',
859      \ '        printf("%d\n", foo);', '    }', '}', '', 'int fact(int n)', '{', '    if(n > 1)', '    {',
860      \ '        return fact(n-1) * n;', '    }', '    return 1;', '}', '', 'int main(int argc, char **argv)',
861      \ '{', '    frobnitz(fact(10));', '}'],
862      \ ['#include <stdio.h>', '', 'int fib(int n)', '{', '    if(n > 2)', '    {',
863      \ '        return fib(n-1) + fib(n-2);', '    }', '    return 1;', '}', '', '// Frobs foo heartily',
864      \ 'int frobnitz(int foo)', '{', '    int i;', '    for(i = 0; i < 10; i++)', '    {',
865      \ '        printf("%d\n", foo);', '    }', '}', '',
866      \ 'int main(int argc, char **argv)', '{', '    frobnitz(fib(10));', '}'])
867  call term_sendkeys(buf, ":diffupdate!\<cr>")
868  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
869  call VerifyScreenDump(buf, 'Test_diff_07', {})
870
871  call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>")
872  call VerifyScreenDump(buf, 'Test_diff_08', {})
873
874  call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
875  call VerifyScreenDump(buf, 'Test_diff_09', {})
876
877  " Test 10-11: normal/indent-heuristic
878  call term_sendkeys(buf, ":set diffopt&vim\<cr>")
879  call WriteDiffFiles(buf, ['', '  def finalize(values)', '', '    values.each do |v|', '      v.finalize', '    end'],
880      \ ['', '  def finalize(values)', '', '    values.each do |v|', '      v.prepare', '    end', '',
881      \ '    values.each do |v|', '      v.finalize', '    end'])
882  call term_sendkeys(buf, ":diffupdate!\<cr>")
883  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
884  call VerifyScreenDump(buf, 'Test_diff_10', {})
885
886  " Leave trailing : at commandline!
887  call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>:\<cr>")
888  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'one')
889  " shouldn't matter, if indent-algorithm comes before or after the algorithm
890  call term_sendkeys(buf, ":set diffopt&\<cr>")
891  call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
892  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'two')
893  call term_sendkeys(buf, ":set diffopt&\<cr>")
894  call term_sendkeys(buf, ":set diffopt+=algorithm:patience,indent-heuristic\<cr>:\<cr>")
895  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'three')
896
897  " Test 12: diff the same file
898  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
899  call VerifyBoth(buf, 'Test_diff_12', '')
900
901  " Test 13: diff an empty file
902  call WriteDiffFiles(buf, [], [])
903  call VerifyBoth(buf, 'Test_diff_13', '')
904
905  " Test 14: test diffopt+=icase
906  call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
907  call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
908
909  " Test 15-16: test diffopt+=iwhite
910  call WriteDiffFiles(buf, ['int main()', '{', '   printf("Hello, World!");', '   return 0;', '}'],
911      \ ['int main()', '{', '   if (0)', '   {', '      printf("Hello, World!");', '      return 0;', '   }', '}'])
912  call term_sendkeys(buf, ":diffupdate!\<cr>")
913  call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
914  call VerifyScreenDump(buf, 'Test_diff_15', {})
915  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
916  call VerifyScreenDump(buf, 'Test_diff_16', {})
917
918  " Test 17: test diffopt+=iblank
919  call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
920  call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
921
922  " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
923  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
924  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
925  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
926
927  " Test 19: test diffopt+=iwhiteeol
928  call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx  xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
929  call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
930
931  " Test 19: test diffopt+=iwhiteall
932  call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
933
934  " clean up
935  call StopVimInTerminal(buf)
936  call delete('Xfile1')
937  call delete('Xfile2')
938endfunc
939
940func Test_diff_with_cursorline()
941  CheckScreendump
942
943  call writefile([
944	\ 'hi CursorLine ctermbg=red ctermfg=white',
945	\ 'set cursorline',
946	\ 'call setline(1, ["foo","foo","foo","bar"])',
947	\ 'vnew',
948	\ 'call setline(1, ["bee","foo","foo","baz"])',
949	\ 'windo diffthis',
950	\ '2wincmd w',
951	\ ], 'Xtest_diff_cursorline')
952  let buf = RunVimInTerminal('-S Xtest_diff_cursorline', {})
953
954  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_01', {})
955  call term_sendkeys(buf, "j")
956  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_02', {})
957  call term_sendkeys(buf, "j")
958  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_03', {})
959
960  " clean up
961  call StopVimInTerminal(buf)
962  call delete('Xtest_diff_cursorline')
963endfunc
964
965func Test_diff_with_syntax()
966  CheckScreendump
967
968  let lines =<< trim END
969  	void doNothing() {
970	   int x = 0;
971	   char *s = "hello";
972	   return 5;
973	}
974  END
975  call writefile(lines, 'Xprogram1.c')
976  let lines =<< trim END
977  	void doSomething() {
978	   int x = 0;
979	   char *s = "there";
980	   return 5;
981	}
982  END
983  call writefile(lines, 'Xprogram2.c')
984
985  let lines =<< trim END
986  	edit Xprogram1.c
987	diffsplit Xprogram2.c
988  END
989  call writefile(lines, 'Xtest_diff_syntax')
990  let buf = RunVimInTerminal('-S Xtest_diff_syntax', {})
991
992  call VerifyScreenDump(buf, 'Test_diff_syntax_1', {})
993
994  " clean up
995  call StopVimInTerminal(buf)
996  call delete('Xtest_diff_syntax')
997  call delete('Xprogram1.c')
998  call delete('Xprogram2.c')
999endfunc
1000
1001func Test_diff_of_diff()
1002  CheckScreendump
1003  CheckFeature rightleft
1004
1005  call writefile([
1006	\ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
1007	\ 'vnew',
1008	\ 'call setline(1, ["aa","bb","cc"])',
1009	\ 'windo diffthis',
1010	\ '1wincmd w',
1011	\ 'setlocal number',
1012	\ ], 'Xtest_diff_diff')
1013  let buf = RunVimInTerminal('-S Xtest_diff_diff', {})
1014
1015  call VerifyScreenDump(buf, 'Test_diff_of_diff_01', {})
1016
1017  call term_sendkeys(buf, ":set rightleft\<cr>")
1018  call VerifyScreenDump(buf, 'Test_diff_of_diff_02', {})
1019
1020  " clean up
1021  call StopVimInTerminal(buf)
1022  call delete('Xtest_diff_diff')
1023endfunc
1024
1025func CloseoffSetup()
1026  enew
1027  call setline(1, ['one', 'two', 'three'])
1028  diffthis
1029  new
1030  call setline(1, ['one', 'tow', 'three'])
1031  diffthis
1032  call assert_equal(1, &diff)
1033  only!
1034endfunc
1035
1036func Test_diff_closeoff()
1037  " "closeoff" included by default: last diff win gets 'diff' reset'
1038  call CloseoffSetup()
1039  call assert_equal(0, &diff)
1040  enew!
1041
1042  " "closeoff" excluded: last diff win keeps 'diff' set'
1043  set diffopt-=closeoff
1044  call CloseoffSetup()
1045  call assert_equal(1, &diff)
1046  diffoff!
1047  enew!
1048endfunc
1049
1050func Test_diff_maintains_change_mark()
1051  enew!
1052  call setline(1, ['a', 'b', 'c', 'd'])
1053  diffthis
1054  new
1055  call setline(1, ['a', 'b', 'c', 'e'])
1056  " Set '[ and '] marks
1057  2,3yank
1058  call assert_equal([2, 3], [line("'["), line("']")])
1059  " Verify they aren't affected by the implicit diff
1060  diffthis
1061  call assert_equal([2, 3], [line("'["), line("']")])
1062  " Verify they aren't affected by an explicit diff
1063  diffupdate
1064  call assert_equal([2, 3], [line("'["), line("']")])
1065  bwipe!
1066  bwipe!
1067endfunc
1068
1069" Test for 'patchexpr'
1070func Test_patchexpr()
1071  let g:patch_args = []
1072  func TPatch()
1073    call add(g:patch_args, readfile(v:fname_in))
1074    call add(g:patch_args, readfile(v:fname_diff))
1075    call writefile(['output file'], v:fname_out)
1076  endfunc
1077  set patchexpr=TPatch()
1078
1079  call writefile(['input file'], 'Xinput')
1080  call writefile(['diff file'], 'Xdiff')
1081  %bwipe!
1082  edit Xinput
1083  diffpatch Xdiff
1084  call assert_equal('output file', getline(1))
1085  call assert_equal('Xinput.new', bufname())
1086  call assert_equal(2, winnr('$'))
1087  call assert_true(&diff)
1088
1089  call delete('Xinput')
1090  call delete('Xdiff')
1091  set patchexpr&
1092  delfunc TPatch
1093  %bwipe!
1094endfunc
1095
1096func Test_diff_rnu()
1097  CheckScreendump
1098
1099  let content =<< trim END
1100    call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
1101    vnew
1102    call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
1103    windo diffthis
1104    setlocal number rnu foldcolumn=0
1105  END
1106  call writefile(content, 'Xtest_diff_rnu')
1107  let buf = RunVimInTerminal('-S Xtest_diff_rnu', {})
1108
1109  call VerifyScreenDump(buf, 'Test_diff_rnu_01', {})
1110
1111  call term_sendkeys(buf, "j")
1112  call VerifyScreenDump(buf, 'Test_diff_rnu_02', {})
1113  call term_sendkeys(buf, "j")
1114  call VerifyScreenDump(buf, 'Test_diff_rnu_03', {})
1115
1116  " clean up
1117  call StopVimInTerminal(buf)
1118  call delete('Xtest_diff_rnu')
1119endfunc
1120
1121" vim: shiftwidth=2 sts=2 expandtab
1122