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