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