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 term_sendkeys(a:buf, ":redraw!\<CR>:")
800  call VerifyScreenDump(a:buf, a:dumpfile, {}, 'unified')
801  call term_sendkeys(a:buf, ":call StopUnified()\<CR>:")
802endfunc
803
804" Verify a screendump with the internal diff only.
805func VerifyInternal(buf, dumpfile, extra)
806  call term_sendkeys(a:buf, ":diffupdate!\<CR>")
807  " trailing : for leaving the cursor on the command line
808  call term_sendkeys(a:buf, ":set diffopt=internal,filler" . a:extra . "\<CR>:")
809  call TermWait(a:buf)
810  call VerifyScreenDump(a:buf, a:dumpfile, {})
811endfunc
812
813func Test_diff_screen()
814  CheckScreendump
815  CheckFeature menu
816
817  let lines =<< trim END
818      func UnifiedDiffExpr()
819        " Prepend some text to check diff type detection
820        call writefile(['warning', '  message'], v:fname_out)
821        silent exe '!diff -U0 ' .. v:fname_in .. ' ' .. v:fname_new .. '>>' .. v:fname_out
822      endfunc
823      func SetupUnified()
824        set diffexpr=UnifiedDiffExpr()
825        diffupdate
826      endfunc
827      func StopUnified()
828        set diffexpr=
829      endfunc
830  END
831  call writefile(lines, 'XdiffSetup')
832
833  " clean up already existing swap files, just in case
834  call delete('.Xfile1.swp')
835  call delete('.Xfile2.swp')
836
837  " Test 1: Add a line in beginning of file 2
838  call WriteDiffFiles(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
839  let buf = RunVimInTerminal('-d -S XdiffSetup Xfile1 Xfile2', {})
840  " Set autoread mode, so that Vim won't complain once we re-write the test
841  " files
842  call term_sendkeys(buf, ":set autoread\<CR>\<c-w>w:set autoread\<CR>\<c-w>w")
843
844  call VerifyBoth(buf, 'Test_diff_01', '')
845
846  " Test 2: Add a line in beginning of file 1
847  call WriteDiffFiles(buf, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
848  call VerifyBoth(buf, 'Test_diff_02', '')
849
850  " Test 3: Add a line at the end of file 2
851  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11])
852  call VerifyBoth(buf, 'Test_diff_03', '')
853
854  " Test 4: Add a line at the end of file 1
855  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
856  call VerifyBoth(buf, 'Test_diff_04', '')
857
858  " Test 5: Add a line in the middle of file 2, remove on at the end of file 1
859  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])
860  call VerifyBoth(buf, 'Test_diff_05', '')
861
862  " Test 6: Add a line in the middle of file 1, remove on at the end of file 2
863  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])
864  call VerifyBoth(buf, 'Test_diff_06', '')
865
866  " Variants on test 6 with different context settings
867  call term_sendkeys(buf, ":set diffopt+=context:2\<cr>")
868  call VerifyScreenDump(buf, 'Test_diff_06.2', {})
869  call term_sendkeys(buf, ":set diffopt-=context:2\<cr>")
870  call term_sendkeys(buf, ":set diffopt+=context:1\<cr>")
871  call VerifyScreenDump(buf, 'Test_diff_06.1', {})
872  call term_sendkeys(buf, ":set diffopt-=context:1\<cr>")
873  call term_sendkeys(buf, ":set diffopt+=context:0\<cr>")
874  call VerifyScreenDump(buf, 'Test_diff_06.0', {})
875  call term_sendkeys(buf, ":set diffopt-=context:0\<cr>")
876
877  " Test 7 - 9: Test normal/patience/histogram diff algorithm
878  call WriteDiffFiles(buf, ['#include <stdio.h>', '', '// Frobs foo heartily', 'int frobnitz(int foo)', '{',
879      \ '    int i;', '    for(i = 0; i < 10; i++)', '    {', '        printf("Your answer is: ");',
880      \ '        printf("%d\n", foo);', '    }', '}', '', 'int fact(int n)', '{', '    if(n > 1)', '    {',
881      \ '        return fact(n-1) * n;', '    }', '    return 1;', '}', '', 'int main(int argc, char **argv)',
882      \ '{', '    frobnitz(fact(10));', '}'],
883      \ ['#include <stdio.h>', '', 'int fib(int n)', '{', '    if(n > 2)', '    {',
884      \ '        return fib(n-1) + fib(n-2);', '    }', '    return 1;', '}', '', '// Frobs foo heartily',
885      \ 'int frobnitz(int foo)', '{', '    int i;', '    for(i = 0; i < 10; i++)', '    {',
886      \ '        printf("%d\n", foo);', '    }', '}', '',
887      \ 'int main(int argc, char **argv)', '{', '    frobnitz(fib(10));', '}'])
888  call term_sendkeys(buf, ":diffupdate!\<cr>")
889  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
890  call VerifyScreenDump(buf, 'Test_diff_07', {})
891
892  call term_sendkeys(buf, ":set diffopt+=algorithm:patience\<cr>")
893  call VerifyScreenDump(buf, 'Test_diff_08', {})
894
895  call term_sendkeys(buf, ":set diffopt+=algorithm:histogram\<cr>")
896  call VerifyScreenDump(buf, 'Test_diff_09', {})
897
898  " Test 10-11: normal/indent-heuristic
899  call term_sendkeys(buf, ":set diffopt&vim\<cr>")
900  call WriteDiffFiles(buf, ['', '  def finalize(values)', '', '    values.each do |v|', '      v.finalize', '    end'],
901      \ ['', '  def finalize(values)', '', '    values.each do |v|', '      v.prepare', '    end', '',
902      \ '    values.each do |v|', '      v.finalize', '    end'])
903  call term_sendkeys(buf, ":diffupdate!\<cr>")
904  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
905  call VerifyScreenDump(buf, 'Test_diff_10', {})
906
907  " Leave trailing : at commandline!
908  call term_sendkeys(buf, ":set diffopt+=indent-heuristic\<cr>:\<cr>")
909  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'one')
910  " shouldn't matter, if indent-algorithm comes before or after the algorithm
911  call term_sendkeys(buf, ":set diffopt&\<cr>")
912  call term_sendkeys(buf, ":set diffopt+=indent-heuristic,algorithm:patience\<cr>:\<cr>")
913  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'two')
914  call term_sendkeys(buf, ":set diffopt&\<cr>")
915  call term_sendkeys(buf, ":set diffopt+=algorithm:patience,indent-heuristic\<cr>:\<cr>")
916  call VerifyScreenDump(buf, 'Test_diff_11', {}, 'three')
917
918  " Test 12: diff the same file
919  call WriteDiffFiles(buf, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [1, 2, 3, 4, 5, 6, 7, 8, 9, 10])
920  call VerifyBoth(buf, 'Test_diff_12', '')
921
922  " Test 13: diff an empty file
923  call WriteDiffFiles(buf, [], [])
924  call VerifyBoth(buf, 'Test_diff_13', '')
925
926  " Test 14: test diffopt+=icase
927  call WriteDiffFiles(buf, ['a', 'b', 'cd'], ['A', 'b', 'cDe'])
928  call VerifyBoth(buf, 'Test_diff_14', " diffopt+=filler diffopt+=icase")
929
930  " Test 15-16: test diffopt+=iwhite
931  call WriteDiffFiles(buf, ['int main()', '{', '   printf("Hello, World!");', '   return 0;', '}'],
932      \ ['int main()', '{', '   if (0)', '   {', '      printf("Hello, World!");', '      return 0;', '   }', '}'])
933  call term_sendkeys(buf, ":diffupdate!\<cr>")
934  call term_sendkeys(buf, ":set diffopt&vim diffopt+=filler diffopt+=iwhite\<cr>")
935  call VerifyScreenDump(buf, 'Test_diff_15', {})
936  call term_sendkeys(buf, ":set diffopt+=internal\<cr>")
937  call VerifyScreenDump(buf, 'Test_diff_16', {})
938
939  " Test 17: test diffopt+=iblank
940  call WriteDiffFiles(buf, ['a', ' ', 'cd', 'ef', 'xxx'], ['a', 'cd', '', 'ef', 'yyy'])
941  call VerifyInternal(buf, 'Test_diff_17', " diffopt+=iblank")
942
943  " Test 18: test diffopt+=iblank,iwhite / iwhiteall / iwhiteeol
944  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhite")
945  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteall")
946  call VerifyInternal(buf, 'Test_diff_18', " diffopt+=iblank,iwhiteeol")
947
948  " Test 19: test diffopt+=iwhiteeol
949  call WriteDiffFiles(buf, ['a ', 'x', 'cd', 'ef', 'xx  xx', 'foo', 'bar'], ['a', 'x', 'c d', ' ef', 'xx xx', 'foo', '', 'bar'])
950  call VerifyInternal(buf, 'Test_diff_19', " diffopt+=iwhiteeol")
951
952  " Test 19: test diffopt+=iwhiteall
953  call VerifyInternal(buf, 'Test_diff_20', " diffopt+=iwhiteall")
954
955  " clean up
956  call StopVimInTerminal(buf)
957  call delete('Xfile1')
958  call delete('Xfile2')
959  call delete('XdiffSetup')
960endfunc
961
962func Test_diff_with_cursorline()
963  CheckScreendump
964
965  call writefile([
966	\ 'hi CursorLine ctermbg=red ctermfg=white',
967	\ 'set cursorline',
968	\ 'call setline(1, ["foo","foo","foo","bar"])',
969	\ 'vnew',
970	\ 'call setline(1, ["bee","foo","foo","baz"])',
971	\ 'windo diffthis',
972	\ '2wincmd w',
973	\ ], 'Xtest_diff_cursorline')
974  let buf = RunVimInTerminal('-S Xtest_diff_cursorline', {})
975
976  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_01', {})
977  call term_sendkeys(buf, "j")
978  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_02', {})
979  call term_sendkeys(buf, "j")
980  call VerifyScreenDump(buf, 'Test_diff_with_cursorline_03', {})
981
982  " clean up
983  call StopVimInTerminal(buf)
984  call delete('Xtest_diff_cursorline')
985endfunc
986
987func Test_diff_with_syntax()
988  CheckScreendump
989
990  let lines =<< trim END
991  	void doNothing() {
992	   int x = 0;
993	   char *s = "hello";
994	   return 5;
995	}
996  END
997  call writefile(lines, 'Xprogram1.c')
998  let lines =<< trim END
999  	void doSomething() {
1000	   int x = 0;
1001	   char *s = "there";
1002	   return 5;
1003	}
1004  END
1005  call writefile(lines, 'Xprogram2.c')
1006
1007  let lines =<< trim END
1008  	edit Xprogram1.c
1009	diffsplit Xprogram2.c
1010  END
1011  call writefile(lines, 'Xtest_diff_syntax')
1012  let buf = RunVimInTerminal('-S Xtest_diff_syntax', {})
1013
1014  call VerifyScreenDump(buf, 'Test_diff_syntax_1', {})
1015
1016  " clean up
1017  call StopVimInTerminal(buf)
1018  call delete('Xtest_diff_syntax')
1019  call delete('Xprogram1.c')
1020  call delete('Xprogram2.c')
1021endfunc
1022
1023func Test_diff_of_diff()
1024  CheckScreendump
1025  CheckFeature rightleft
1026
1027  call writefile([
1028	\ 'call setline(1, ["aa","bb","cc","@@ -3,2 +5,7 @@","dd","ee","ff"])',
1029	\ 'vnew',
1030	\ 'call setline(1, ["aa","bb","cc"])',
1031	\ 'windo diffthis',
1032	\ '1wincmd w',
1033	\ 'setlocal number',
1034	\ ], 'Xtest_diff_diff')
1035  let buf = RunVimInTerminal('-S Xtest_diff_diff', {})
1036
1037  call VerifyScreenDump(buf, 'Test_diff_of_diff_01', {})
1038
1039  call term_sendkeys(buf, ":set rightleft\<cr>")
1040  call VerifyScreenDump(buf, 'Test_diff_of_diff_02', {})
1041
1042  " clean up
1043  call StopVimInTerminal(buf)
1044  call delete('Xtest_diff_diff')
1045endfunc
1046
1047func CloseoffSetup()
1048  enew
1049  call setline(1, ['one', 'two', 'three'])
1050  diffthis
1051  new
1052  call setline(1, ['one', 'tow', 'three'])
1053  diffthis
1054  call assert_equal(1, &diff)
1055  only!
1056endfunc
1057
1058func Test_diff_closeoff()
1059  " "closeoff" included by default: last diff win gets 'diff' reset'
1060  call CloseoffSetup()
1061  call assert_equal(0, &diff)
1062  enew!
1063
1064  " "closeoff" excluded: last diff win keeps 'diff' set'
1065  set diffopt-=closeoff
1066  call CloseoffSetup()
1067  call assert_equal(1, &diff)
1068  diffoff!
1069  enew!
1070endfunc
1071
1072func Test_diff_followwrap()
1073  new
1074  set diffopt+=followwrap
1075  set wrap
1076  diffthis
1077  call assert_equal(1, &wrap)
1078  diffoff
1079  set nowrap
1080  diffthis
1081  call assert_equal(0, &wrap)
1082  diffoff
1083  set diffopt&
1084  bwipe!
1085endfunc
1086
1087func Test_diff_maintains_change_mark()
1088  enew!
1089  call setline(1, ['a', 'b', 'c', 'd'])
1090  diffthis
1091  new
1092  call setline(1, ['a', 'b', 'c', 'e'])
1093  " Set '[ and '] marks
1094  2,3yank
1095  call assert_equal([2, 3], [line("'["), line("']")])
1096  " Verify they aren't affected by the implicit diff
1097  diffthis
1098  call assert_equal([2, 3], [line("'["), line("']")])
1099  " Verify they aren't affected by an explicit diff
1100  diffupdate
1101  call assert_equal([2, 3], [line("'["), line("']")])
1102  bwipe!
1103  bwipe!
1104endfunc
1105
1106" Test for 'patchexpr'
1107func Test_patchexpr()
1108  let g:patch_args = []
1109  func TPatch()
1110    call add(g:patch_args, readfile(v:fname_in))
1111    call add(g:patch_args, readfile(v:fname_diff))
1112    call writefile(['output file'], v:fname_out)
1113  endfunc
1114  set patchexpr=TPatch()
1115
1116  call writefile(['input file'], 'Xinput')
1117  call writefile(['diff file'], 'Xdiff')
1118  %bwipe!
1119  edit Xinput
1120  diffpatch Xdiff
1121  call assert_equal('output file', getline(1))
1122  call assert_equal('Xinput.new', bufname())
1123  call assert_equal(2, winnr('$'))
1124  call assert_true(&diff)
1125
1126  call delete('Xinput')
1127  call delete('Xdiff')
1128  set patchexpr&
1129  delfunc TPatch
1130  %bwipe!
1131endfunc
1132
1133func Test_diff_rnu()
1134  CheckScreendump
1135
1136  let content =<< trim END
1137    call setline(1, ['a', 'a', 'a', 'y', 'b', 'b', 'b', 'b', 'b'])
1138    vnew
1139    call setline(1, ['a', 'a', 'a', 'x', 'x', 'x', 'b', 'b', 'b', 'b', 'b'])
1140    windo diffthis
1141    setlocal number rnu foldcolumn=0
1142  END
1143  call writefile(content, 'Xtest_diff_rnu')
1144  let buf = RunVimInTerminal('-S Xtest_diff_rnu', {})
1145
1146  call VerifyScreenDump(buf, 'Test_diff_rnu_01', {})
1147
1148  call term_sendkeys(buf, "j")
1149  call VerifyScreenDump(buf, 'Test_diff_rnu_02', {})
1150  call term_sendkeys(buf, "j")
1151  call VerifyScreenDump(buf, 'Test_diff_rnu_03', {})
1152
1153  " clean up
1154  call StopVimInTerminal(buf)
1155  call delete('Xtest_diff_rnu')
1156endfunc
1157
1158func Test_diff_multilineconceal()
1159  new
1160  diffthis
1161
1162  new
1163  call matchadd('Conceal', 'a\nb', 9, -1, {'conceal': 'Y'})
1164  set cole=2 cocu=n
1165  call setline(1, ["a", "b"])
1166  diffthis
1167  redraw
1168endfunc
1169
1170func Test_diff_and_scroll()
1171  " this was causing an ml_get error
1172  set ls=2
1173  for i in range(winheight(0) * 2)
1174    call setline(i, i < winheight(0) - 10 ? i : i + 10)
1175  endfor
1176  vnew
1177  for i in range(winheight(0)*2 + 10)
1178    call setline(i, i < winheight(0) - 10 ? 0 : i)
1179  endfor
1180  diffthis
1181  wincmd p
1182  diffthis
1183  execute 'normal ' . winheight(0) . "\<C-d>"
1184
1185  bwipe!
1186  bwipe!
1187  set ls&
1188endfunc
1189
1190func Test_diff_filler_cursorcolumn()
1191  CheckScreendump
1192
1193  let content =<< trim END
1194    call setline(1, ['aa', 'bb', 'cc'])
1195    vnew
1196    call setline(1, ['aa', 'cc'])
1197    windo diffthis
1198    wincmd p
1199    setlocal cursorcolumn foldcolumn=0
1200    norm! gg0
1201    redraw!
1202  END
1203  call writefile(content, 'Xtest_diff_cuc')
1204  let buf = RunVimInTerminal('-S Xtest_diff_cuc', {})
1205
1206  call VerifyScreenDump(buf, 'Test_diff_cuc_01', {})
1207
1208  call term_sendkeys(buf, "l")
1209  call term_sendkeys(buf, "\<C-l>")
1210  call VerifyScreenDump(buf, 'Test_diff_cuc_02', {})
1211  call term_sendkeys(buf, "0j")
1212  call term_sendkeys(buf, "\<C-l>")
1213  call VerifyScreenDump(buf, 'Test_diff_cuc_03', {})
1214  call term_sendkeys(buf, "l")
1215  call term_sendkeys(buf, "\<C-l>")
1216  call VerifyScreenDump(buf, 'Test_diff_cuc_04', {})
1217
1218  " clean up
1219  call StopVimInTerminal(buf)
1220  call delete('Xtest_diff_cuc')
1221endfunc
1222
1223
1224" vim: shiftwidth=2 sts=2 expandtab
1225