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  if !executable('diff')
625    return
626  endif
627
628  func DiffExpr()
629    " Prepent some text to check diff type detection
630    call writefile(['warning', '  message'], v:fname_out)
631    silent exe '!diff ' . v:fname_in . ' ' . v:fname_new . '>>' . v:fname_out
632  endfunc
633  set diffexpr=DiffExpr()
634  set diffopt=foldcolumn:0
635
636  enew!
637  call setline(1, ['one', 'two', 'three'])
638  redraw
639  let normattr = screenattr(1, 1)
640  diffthis
641
642  botright vert new
643  call setline(1, ['one', 'two', 'three.'])
644  diffthis
645
646  redraw
647  call assert_equal(normattr, screenattr(1, 1))
648  call assert_equal(normattr, screenattr(2, 1))
649  call assert_notequal(normattr, screenattr(3, 1))
650
651  diffoff!
652  %bwipe!
653  set diffexpr& diffopt&
654endfunc
655
656func Test_diffpatch()
657  " The patch program on MS-Windows may fail or hang.
658  CheckExecutable patch
659  CheckUnix
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
1121func Test_diff_multilineconceal()
1122  new
1123  diffthis
1124
1125  new
1126  call matchadd('Conceal', 'a\nb', 9, -1, {'conceal': 'Y'})
1127  set cole=2 cocu=n
1128  call setline(1, ["a", "b"])
1129  diffthis
1130  redraw
1131endfunc
1132
1133func Test_diff_and_scroll()
1134  " this was causing an ml_get error
1135  set ls=2
1136  for i in range(winheight(0) * 2)
1137    call setline(i, i < winheight(0) - 10 ? i : i + 10)
1138  endfor
1139  vnew
1140  for i in range(winheight(0)*2 + 10)
1141    call setline(i, i < winheight(0) - 10 ? 0 : i)
1142  endfor
1143  diffthis
1144  wincmd p
1145  diffthis
1146  execute 'normal ' . winheight(0) . "\<C-d>"
1147
1148  bwipe!
1149  bwipe!
1150  set ls&
1151endfunc
1152
1153" vim: shiftwidth=2 sts=2 expandtab
1154