1 /*
2  * Incomplete regression tests for the diff/diff3 library.
3  *
4  * ====================================================================
5  *    Licensed to the Apache Software Foundation (ASF) under one
6  *    or more contributor license agreements.  See the NOTICE file
7  *    distributed with this work for additional information
8  *    regarding copyright ownership.  The ASF licenses this file
9  *    to you under the Apache License, Version 2.0 (the
10  *    "License"); you may not use this file except in compliance
11  *    with the License.  You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  *    Unless required by applicable law or agreed to in writing,
16  *    software distributed under the License is distributed on an
17  *    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
18  *    KIND, either express or implied.  See the License for the
19  *    specific language governing permissions and limitations
20  *    under the License.
21  * ====================================================================
22  */
23 
24 
25 #include "../svn_test.h"
26 
27 #include "svn_diff.h"
28 #include "svn_pools.h"
29 #include "svn_utf.h"
30 
31 /* Used to terminate lines in large multi-line string literals. */
32 #define NL APR_EOL_STR
33 
34 /* Random number seed.  Yes, it's global, just pretend you can't see it. */
35 static apr_uint32_t diff_diff3_seed;
36 
37 /* Return the value of the current random number seed, initializing it if
38    necessary */
39 static apr_uint32_t
seed_val(void)40 seed_val(void)
41 {
42   static svn_boolean_t first = TRUE;
43 
44   if (first)
45     {
46       diff_diff3_seed = (apr_uint32_t) apr_time_now();
47       first = FALSE;
48     }
49 
50   return diff_diff3_seed;
51 }
52 
53 /* Return a random number N such that MIN_VAL <= N <= MAX_VAL */
54 static apr_uint32_t
range_rand(apr_uint32_t min_val,apr_uint32_t max_val)55 range_rand(apr_uint32_t min_val,
56            apr_uint32_t max_val)
57 {
58   apr_uint64_t diff = max_val - min_val;
59   apr_uint64_t val = diff * svn_test_rand(&diff_diff3_seed);
60   val /= 0xffffffff;
61   return min_val + (apr_uint32_t) val;
62 }
63 
64 /* Make a file that is between MIN_LINES and MAX_LINES lines long, with at
65    most VAR_LINES distinct lines.  If BLOCK_LINES is non-zero then every
66    other block of BLOCK_LINES lines will be identical, if BLOCK_LINES is
67    zero all lines will have contents chosen at random.  If TRAILING_NEWLINE
68    is TRUE then the file will have a trailing newline, if not then it wont. */
69 static svn_error_t *
make_random_file(const char * filename,int min_lines,int max_lines,int var_lines,int block_lines,svn_boolean_t trailing_newline,apr_pool_t * pool)70 make_random_file(const char *filename,
71                  int min_lines,
72                  int max_lines,
73                  int var_lines,
74                  int block_lines,
75                  svn_boolean_t trailing_newline,
76                  apr_pool_t *pool)
77 {
78   apr_file_t *file;
79   int num_lines;
80 
81   num_lines = range_rand(min_lines, max_lines);
82 
83   SVN_ERR(svn_io_file_open(&file, filename,
84                            APR_WRITE | APR_CREATE | APR_TRUNCATE,
85                            APR_OS_DEFAULT,
86                            pool));
87 
88   while (num_lines--)
89     {
90       int x;
91       if (! (block_lines && (num_lines / block_lines % 2)))
92         x = range_rand(1, var_lines);
93       else
94         x = 0;
95       if (num_lines || trailing_newline)
96         apr_file_printf(file, "line %d line %d line %d\n", x, x, x);
97       else
98         apr_file_printf(file, "line %d line %d line %d", x, x, x);
99     }
100 
101   SVN_ERR(svn_io_file_close(file, pool));
102 
103   return SVN_NO_ERROR;
104 }
105 
106 
107 /* Create a file called FILENAME containing CONTENTS */
108 static svn_error_t *
make_file(const char * filename,const char * contents,apr_pool_t * pool)109 make_file(const char *filename,
110           const char *contents,
111           apr_pool_t *pool)
112 {
113   apr_file_t *file;
114   apr_status_t status;
115 
116   SVN_ERR(svn_io_file_open(&file, filename,
117                            APR_WRITE | APR_CREATE | APR_TRUNCATE,
118                            APR_OS_DEFAULT, pool));
119 
120   status = apr_file_write_full(file, contents, strlen(contents), NULL);
121   if (status)
122     return svn_error_createf(status, NULL, "failed to write '%s'", filename);
123 
124   SVN_ERR(svn_io_file_close(file, pool));
125 
126   return SVN_NO_ERROR;
127 }
128 
129 
130 /* Create three files called FILENAME1, FILENAME2 and FILENAME3
131    containing CONTENTS1, CONTENTS2 and CONTENTS3 respectively.  Run a
132    three way merge to merge the difference between CONTENTS1 and
133    CONTENTS2 into CONTENTS3, using OPTIONS, and verify that it results
134    in EXPECTED.  The files FILENAME1, FILENAME2 and FILENAME3 will be
135    deleted if the merge is successful, and preserved otherwise.  If
136    the merge fails the merge output will be in a file called
137    "merge-FILENAME1-FILENAME2-FILENAME3".  The conflict style STYLE is
138    used. */
139 static svn_error_t *
three_way_merge(const char * base_filename1,const char * base_filename2,const char * base_filename3,const char * contents1,const char * contents2,const char * contents3,const char * expected,const svn_diff_file_options_t * options,svn_diff_conflict_display_style_t style,apr_pool_t * pool)140 three_way_merge(const char *base_filename1,
141                 const char *base_filename2,
142                 const char *base_filename3,
143                 const char *contents1,
144                 const char *contents2,
145                 const char *contents3,
146                 const char *expected,
147                 const svn_diff_file_options_t *options,
148                 svn_diff_conflict_display_style_t style,
149                 apr_pool_t *pool)
150 {
151   svn_diff_t *diff;
152   apr_file_t *output;
153   svn_stream_t *ostream;
154   svn_stringbuf_t *actual;
155   char *merge_name = apr_psprintf(
156       pool, "merge-%s-%s-%s", base_filename1, base_filename2, base_filename3);
157 
158   const char *filename1 = svn_test_data_path(base_filename1, pool);
159   const char *filename2 = svn_test_data_path(base_filename2, pool);
160   const char *filename3 = svn_test_data_path(base_filename3, pool);
161 
162   /* We have an EXPECTED string we can match, because we don't support
163      any other combinations (yet) than the ones above. */
164   svn_string_t *original = svn_string_create(contents1, pool);
165   svn_string_t *modified = svn_string_create(contents2, pool);
166   svn_string_t *latest = svn_string_create(contents3, pool);
167 
168   options = options ? options : svn_diff_file_options_create(pool);
169 
170   SVN_ERR(svn_diff_mem_string_diff3(&diff,
171                                     original, modified, latest, options, pool));
172 
173   actual = svn_stringbuf_create_empty(pool);
174   ostream = svn_stream_from_stringbuf(actual, pool);
175 
176   SVN_ERR(svn_diff_mem_string_output_merge3
177           (ostream, diff, original, modified, latest,
178            apr_psprintf(pool, "||||||| %s", base_filename1),
179            apr_psprintf(pool, "<<<<<<< %s", base_filename2),
180            apr_psprintf(pool, ">>>>>>> %s", base_filename3),
181            NULL, /* separator */
182            style,
183            NULL, NULL, /* cancel */
184            pool));
185 
186   SVN_ERR(svn_stream_close(ostream));
187   if (strcmp(actual->data, expected) != 0)
188     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
189                              "Failed mem-diff, expected and actual "
190                              "outputs differ.\nEXPECTED:\n%s\n"
191                              "ACTUAL:\n%s\n", expected, actual->data);
192 
193   SVN_ERR(make_file(filename1, contents1, pool));
194   SVN_ERR(make_file(filename2, contents2, pool));
195   SVN_ERR(make_file(filename3, contents3, pool));
196 
197   SVN_ERR(svn_diff_file_diff3_2(&diff, filename1, filename2, filename3,
198                                 options, pool));
199   SVN_ERR(svn_io_file_open(&output, merge_name,
200                            APR_WRITE | APR_CREATE | APR_TRUNCATE,
201                            APR_OS_DEFAULT, pool));
202 
203   ostream = svn_stream_from_aprfile2(output, FALSE, pool);
204   SVN_ERR(svn_diff_file_output_merge3(
205               ostream, diff,
206               filename1, filename2, filename3,
207               apr_psprintf(pool, "||||||| %s", base_filename1),
208               apr_psprintf(pool, "<<<<<<< %s", base_filename2),
209               apr_psprintf(pool, ">>>>>>> %s", base_filename3),
210               NULL, /* separator */
211               style,
212               NULL, NULL, /* cancel */
213               pool));
214   SVN_ERR(svn_stream_close(ostream));
215   SVN_ERR(svn_stringbuf_from_file2(&actual, merge_name, pool));
216   if (strcmp(actual->data, expected))
217     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
218                              "failed merging diff '%s' to '%s' into '%s'",
219                              base_filename1, base_filename2, base_filename3);
220 
221   SVN_ERR(svn_io_remove_file2(filename1, TRUE, pool));
222   if (strcmp(filename1, filename2))
223     SVN_ERR(svn_io_remove_file2(filename2, TRUE, pool));
224   if (strcmp(filename1, filename3) && strcmp(filename2, filename3))
225     SVN_ERR(svn_io_remove_file2(filename3, TRUE, pool));
226   SVN_ERR(svn_io_remove_file2(merge_name, TRUE, pool));
227 
228   return SVN_NO_ERROR;
229 }
230 
231 
232 /* Create two files called FILENAME1 and FILENAME2 containing
233    CONTENTS1 and CONTENTS2 respectively.  Run a two way diff between
234    CONTENTS1 and CONTENTS2, using OPTIONS, and verify that it results
235    in EXPECTED.  Then run the trivial merges to update CONTENTS1 to
236    CONTENTS2 and CONTENTS2 to CONTENTS1. The files FILENAME1,
237    FILENAME2 and be deleted if the diff and merges are successful, and
238    preserved otherwise.  If the diff fails the diff output will be in
239    a file called "diff-FILENAME1-FILENAME2".  */
240 static svn_error_t *
two_way_diff(const char * base_filename1,const char * base_filename2,const char * contents1,const char * contents2,const char * expected,const svn_diff_file_options_t * options,apr_pool_t * pool)241 two_way_diff(const char *base_filename1,
242              const char *base_filename2,
243              const char *contents1,
244              const char *contents2,
245              const char *expected,
246              const svn_diff_file_options_t *options,
247              apr_pool_t *pool)
248 {
249   svn_diff_t *diff;
250   apr_file_t *output;
251   svn_stream_t *ostream;
252   svn_stringbuf_t *actual;
253   char *diff_name = (char *)apr_pstrdup(
254       pool, svn_test_data_path(
255           apr_psprintf(pool, "diff-%s-%s", base_filename1, base_filename2),
256           pool));
257 
258   const char *filename1 = svn_test_data_path(base_filename1, pool);
259   const char *filename2 = svn_test_data_path(base_filename2, pool);
260 
261   /* Some of the tests have lots of lines, although not much data as
262      the lines are short, and the in-memory diffs allocate a lot of
263      memory.  Since we are doing multiple diff in a single test we use
264      a subpool to reuse that memory. */
265   apr_pool_t *subpool = svn_pool_create(pool);
266 
267   /* We have an EXPECTED string we can match, because we don't support
268      any other combinations (yet) than the ones above. */
269   svn_string_t *original = svn_string_create(contents1, pool);
270   svn_string_t *modified = svn_string_create(contents2, pool);
271 
272   options = options ? options : svn_diff_file_options_create(pool);
273 
274   SVN_ERR(svn_diff_mem_string_diff(&diff, original, modified, options,
275                                    subpool));
276 
277   actual = svn_stringbuf_create_empty(pool);
278   ostream = svn_stream_from_stringbuf(actual, pool);
279 
280   SVN_ERR(svn_diff_mem_string_output_unified(ostream, diff,
281                                              base_filename1, base_filename2,
282                                              SVN_APR_LOCALE_CHARSET,
283                                              original, modified, subpool));
284   svn_pool_clear(subpool);
285   SVN_ERR(svn_stream_close(ostream));
286   if (strcmp(actual->data, expected) != 0)
287     return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
288                              "Failed mem-diff, expected and actual "
289                              "outputs differ.\nEXPECTED:\n%s\n"
290                              "ACTUAL:\n%s\n", expected, actual->data);
291 
292   SVN_ERR(make_file(filename1, contents1, pool));
293   SVN_ERR(make_file(filename2, contents2, pool));
294 
295   /* Check that two-way diff between contents1 and contents2 produces
296      expected output. */
297   SVN_ERR(svn_diff_file_diff_2(&diff, filename1, filename2, options, pool));
298 
299   SVN_ERR(svn_io_file_open(&output, diff_name,
300                            APR_WRITE | APR_CREATE | APR_TRUNCATE,
301                            APR_OS_DEFAULT, pool));
302 
303   ostream = svn_stream_from_aprfile2(output, FALSE, pool);
304   SVN_ERR(svn_diff_file_output_unified2(ostream, diff,
305                                         filename1, filename2,
306                                         base_filename1, base_filename2,
307                                         SVN_APR_LOCALE_CHARSET, pool));
308   SVN_ERR(svn_stream_close(ostream));
309 
310   SVN_ERR(svn_stringbuf_from_file2(&actual, diff_name, pool));
311   if (strcmp(actual->data, expected))
312     {
313       /*svn_stringbuf_t *dump_actual;
314       svn_stream_t *dump_ostream;
315       dump_actual = svn_stringbuf_create_empty(pool);
316       dump_ostream = svn_stream_from_stringbuf(dump_actual, pool);
317 
318       SVN_ERR(svn_diff_mem_string_output_unified(dump_ostream, diff,
319                                                  "expected", "actual",
320                                                  SVN_APR_LOCALE_CHARSET,
321                                                  svn_string_create(expected, pool),
322                                                  svn_string_create(actual->data, pool),
323                                                  pool));
324       SVN_ERR(svn_stream_close(ostream));
325 
326       SVN_DBG(("%s\n", dump_actual->data));
327 
328       SVN_ERR(make_file("memory", expected, pool));*/
329       return svn_error_createf(SVN_ERR_TEST_FAILED, NULL,
330                                "failed comparing '%s' and '%s'"
331                                " (memory and file results are different)",
332                                base_filename1, base_filename2);
333     }
334 
335   /* May as well do the trivial merges while we are here */
336   SVN_ERR(three_way_merge(base_filename1, base_filename2, base_filename1,
337                           contents1, contents2, contents1, contents2, NULL,
338                           svn_diff_conflict_display_modified_latest,
339                           subpool));
340   svn_pool_clear(subpool);
341   SVN_ERR(three_way_merge(base_filename2, base_filename1, base_filename2,
342                           contents2, contents1, contents2, contents1, NULL,
343                           svn_diff_conflict_display_modified_latest,
344                           subpool));
345   svn_pool_destroy(subpool);
346 
347   SVN_ERR(svn_io_remove_file2(diff_name, TRUE, pool));
348 
349   return SVN_NO_ERROR;
350 }
351 
352 struct random_mod
353 {
354   int index;  /* Zero based line number */
355   int mod;    /* Type of mod: 0, 1, 2 (can be interpreted as you like just
356                  do it consistently) */
357 };
358 
359 /* Fill the SELECTED array of length NUM to select with randomly chosen
360    values, ensuring that none of SELECTED.INDEX are duplicates and that all
361    the SELECTED.INDEX values are less than NUM_LINES.  Also ensure that for
362    each SELECTED.INDEX the three elements of LINES from SELECTED.INDEX-1 to
363    SELECTED.INDEX+1 are unset.  Set all LINES[SELECTED.INDEX]. */
364 static void
select_lines(struct random_mod * selected,int num_to_select,svn_boolean_t * lines,int num_lines)365 select_lines(struct random_mod *selected,
366              int num_to_select,
367              svn_boolean_t *lines,
368              int num_lines)
369 {
370   int i;
371   for (i = 0; i < num_to_select; ++i)
372     {
373       int j;
374       for (;;)
375         {
376           j= range_rand(0, num_lines - 1);
377           if (lines[j] /* already selected */
378               ||
379               (j > 0 && lines[j - 1]) /* previous selected */
380               ||
381               (j < num_lines - 1 && lines[j + 1])) /* next selected */
382             continue; /* try again */
383           break; /* got one */
384         }
385       selected[i].index = j;
386       selected[i].mod = range_rand(0, 2);
387       lines[j] = TRUE;
388     }
389 }
390 
391 
392 /* Create a file called FILENAME where the contents are obtained by
393    applying the modifications in MOD_LINES, of which there are NUM_MODS, to
394    a theoretical pristine file of length NUM_LINES lines. */
395 static svn_error_t *
make_random_merge_file(const char * filename,int num_lines,struct random_mod * mod_lines,int num_mods,apr_pool_t * pool)396 make_random_merge_file(const char *filename,
397                        int num_lines,
398                        struct random_mod *mod_lines,
399                        int num_mods,
400                        apr_pool_t *pool)
401 {
402   apr_file_t *file;
403   int i;
404 
405   SVN_ERR(svn_io_file_open(&file, filename,
406                            APR_WRITE | APR_CREATE | APR_TRUNCATE,
407                            APR_OS_DEFAULT, pool));
408 
409   for (i = 0; i < num_lines; ++i)
410     {
411       int j;
412       for (j = 0; j < num_mods; ++j)
413         if (mod_lines[j].index == i)
414           break;
415 
416       if (j < num_mods)
417         {
418           switch (mod_lines[j].mod)
419             {
420             case 0:
421               apr_file_printf(file, "replace line %d\n", i);
422               break;
423             case 1:
424               apr_file_printf(file,
425                               "added line %d\n"
426                               "unmodified line %d\n"
427                               "added line %d\n",
428                               i, i, i);
429               break;
430             default:
431               ; /* Delete the line */
432             }
433         }
434       else
435         {
436           apr_file_printf(file, "unmodified line %d\n", i);
437         }
438     }
439 
440   SVN_ERR(svn_io_file_close(file, pool));
441 
442   return SVN_NO_ERROR;
443 }
444 
445 
446 /* ========================================================================== */
447 
448 static svn_error_t *
dump_core(apr_pool_t * pool)449 dump_core(apr_pool_t *pool)
450 {
451   SVN_ERR(two_way_diff("foo1", "bar1",
452                        "",
453                        "",
454                        "",
455                        NULL, pool));
456 
457   SVN_ERR(two_way_diff("foo2", "bar2",
458                        "Aa\n"
459                        "Bb\n"
460                        "Cc\n",
461 
462                        "",
463 
464                        "--- foo2"         NL
465                        "+++ bar2"         NL
466                        "@@ -1,3 +0,0 @@"  NL
467                        "-Aa\n"
468                        "-Bb\n"
469                        "-Cc\n",
470                        NULL, pool));
471 
472   SVN_ERR(two_way_diff("foo3", "bar3",
473                        "",
474 
475                        "Aa\n"
476                        "Bb\n"
477                        "Cc\n",
478 
479                        "--- foo3"         NL
480                        "+++ bar3"         NL
481                        "@@ -0,0 +1,3 @@"  NL
482                        "+Aa\n"
483                        "+Bb\n"
484                        "+Cc\n",
485                        NULL, pool));
486 
487   return SVN_NO_ERROR;
488 }
489 
490 
491 static svn_error_t *
test_two_way_unified(apr_pool_t * pool)492 test_two_way_unified(apr_pool_t *pool)
493 {
494   svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
495 
496   SVN_ERR(two_way_diff("foo4", "bar4",
497                        "Aa\n",
498 
499                        "Aa\n"
500                        "Bb\n"
501                        "Cc\n",
502 
503                        "--- foo4"       NL
504                        "+++ bar4"       NL
505                        "@@ -1 +1,3 @@"  NL
506                        " Aa\n"
507                        "+Bb\n"
508                        "+Cc\n",
509                        NULL, pool));
510 
511   SVN_ERR(two_way_diff("foo4b", "bar4b",
512                        "Cc\n",
513 
514                        "Aa\n"
515                        "Bb\n"
516                        "Cc\n",
517 
518                        "--- foo4b"      NL
519                        "+++ bar4b"      NL
520                        "@@ -1 +1,3 @@"  NL
521                        "+Aa\n"
522                        "+Bb\n"
523                        " Cc\n",
524                        NULL, pool));
525 
526   diff_opts->ignore_eol_style = TRUE;
527   SVN_ERR(two_way_diff("foo4c", "bar4c",
528                        "Cc\n",
529 
530                        "Aa\r"
531                        "Bb\r"
532                        "Cc\r",
533 
534                        "--- foo4c"      NL
535                        "+++ bar4c"      NL
536                        "@@ -1 +1,3 @@"  NL
537                        "+Aa\r"
538                        "+Bb\r"
539                        " Cc\n",
540                        diff_opts, pool));
541   diff_opts->ignore_eol_style = FALSE;
542 
543   SVN_ERR(two_way_diff("foo5", "bar5",
544                        "Aa\n"
545                        "Bb\n"
546                        "Cc\n",
547 
548                        "Aa\n",
549 
550                        "--- foo5"       NL
551                        "+++ bar5"       NL
552                        "@@ -1,3 +1 @@"  NL
553                        " Aa\n"
554                        "-Bb\n"
555                        "-Cc\n",
556                        NULL, pool));
557 
558   SVN_ERR(two_way_diff("foo5b", "bar5b",
559                        "Aa\n"
560                        "Bb\n"
561                        "Cc\n",
562 
563                        "Cc\n",
564 
565                        "--- foo5b"      NL
566                        "+++ bar5b"      NL
567                        "@@ -1,3 +1 @@"  NL
568                        "-Aa\n"
569                        "-Bb\n"
570                        " Cc\n",
571                        NULL, pool));
572 
573   diff_opts->ignore_eol_style = TRUE;
574   SVN_ERR(two_way_diff("foo5c", "bar5c",
575                        "Aa\r\n"
576                        "Bb\r\n"
577                        "Cc\r\n",
578 
579                        "Cc\n",
580 
581                        "--- foo5c"      NL
582                        "+++ bar5c"      NL
583                        "@@ -1,3 +1 @@"  NL
584                        "-Aa\r\n"
585                        "-Bb\r\n"
586                        " Cc\r\n",
587                        diff_opts, pool));
588 
589 
590   SVN_ERR(two_way_diff("foo5d", "bar5d",
591                        "Aa\r\n"
592                        "\r\n"
593                        "Bb\r\n"
594                        "\r\n"
595                        "Cc\r\n"
596                        "\r\n",
597 
598                        "Aa\n"
599                        "\n"
600                        "Bb\n"
601                        "\n"
602                        "Cc\n"
603                        "\n",
604 
605                        "",
606                        diff_opts, pool));
607   diff_opts->ignore_eol_style = FALSE;
608 
609   SVN_ERR(two_way_diff("foo6", "bar6",
610                        "Aa\n"
611                        "Bb\n"
612                        "Cc\n",
613 
614                        "Aa\n"
615                        "Bb\n"
616                        "Cc\n",
617 
618                        "",
619                        NULL, pool));
620 
621   SVN_ERR(two_way_diff("foo6b", "bar6b",
622                        "Aa\n"
623                        "Bb\n"
624                        "Cc\n",
625 
626                        "Aa\n"
627                        "Xx\n"
628                        "Cc\n",
629 
630                        "--- foo6b"        NL
631                        "+++ bar6b"        NL
632                        "@@ -1,3 +1,3 @@"  NL
633                        " Aa\n"
634                        "-Bb\n"
635                        "+Xx\n"
636                        " Cc\n",
637                        NULL, pool));
638 
639   SVN_ERR(two_way_diff("foo6c", "bar6c",
640                        "Aa\r\n"
641                        "Bb\r\n"
642                        "Cc\r\n",
643 
644                        "Aa\r\n"
645                        "Xx\r\n"
646                        "Cc\r\n",
647 
648                        "--- foo6c"        NL
649                        "+++ bar6c"        NL
650                        "@@ -1,3 +1,3 @@"  NL
651                        " Aa\r\n"
652                        "-Bb\r\n"
653                        "+Xx\r\n"
654                        " Cc\r\n",
655                        NULL, pool));
656 
657   SVN_ERR(two_way_diff("foo6d", "bar6d",
658                        "Aa\r"
659                        "Bb\r"
660                        "Cc\r",
661 
662                        "Aa\r"
663                        "Xx\r"
664                        "Cc\r",
665 
666                        "--- foo6d"        NL
667                        "+++ bar6d"        NL
668                        "@@ -1,3 +1,3 @@"  NL
669                        " Aa\r"
670                        "-Bb\r"
671                        "+Xx\r"
672                        " Cc\r",
673                        NULL, pool));
674 
675   diff_opts->ignore_space = svn_diff_file_ignore_space_change;
676   SVN_ERR(two_way_diff("foo6e", "bar6e",
677                        " A a \n"
678                        " B b \r"
679                        " C c \r\n",
680 
681                        " A  a   \n"
682                        "   B b  \r"
683                        "    C    c    \r\n",
684 
685                        "",
686                        diff_opts, pool));
687   diff_opts->ignore_space = svn_diff_file_ignore_space_none;
688 
689   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
690   SVN_ERR(two_way_diff("foo6f", "bar6f",
691                        "Aa\n"
692                        "Bb\r"
693                        "Cc\r\n",
694 
695                        " A  a   \n"
696                        "   B b  \r"
697                        "    C    c    \r\n",
698 
699                        "",
700                        diff_opts, pool));
701   diff_opts->ignore_space = svn_diff_file_ignore_space_none;
702 
703   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
704   diff_opts->ignore_eol_style = TRUE;
705   SVN_ERR(two_way_diff("foo6f", "bar6f",
706                        "Aa\n"
707                        "Bb\r"
708                        "Cc\r\n",
709 
710                        " A  a   \r"
711                        "   B b  \r\n"
712                        "    C    c    \n",
713 
714                        "",
715                        diff_opts, pool));
716   diff_opts->ignore_space = svn_diff_file_ignore_space_none;
717   diff_opts->ignore_eol_style = FALSE;
718 
719   SVN_ERR(two_way_diff("foo7", "bar7",
720                        "Aa\n",
721 
722                        "Bb\n",
723 
724                        "--- foo7"     NL
725                        "+++ bar7"     NL
726                        "@@ -1 +1 @@"  NL
727                        "-Aa\n"
728                        "+Bb\n",
729                        NULL, pool));
730 
731   SVN_ERR(two_way_diff("foo7a", "bar7a",
732                        "Aa\n"
733                        "Cc\n",
734 
735                        "Bb\n"
736                        "Cc\n",
737 
738                        "--- foo7a"        NL
739                        "+++ bar7a"        NL
740                        "@@ -1,2 +1,2 @@"  NL
741                        "-Aa\n"
742                        "+Bb\n"
743                        " Cc\n",
744                        NULL, pool));
745 
746   SVN_ERR(two_way_diff("foo7b", "bar7b",
747                        "Aa\r"
748                        "Cc\n",
749 
750                        "Bb\n"
751                        "Cc\n",
752 
753                        "--- foo7b"        NL
754                        "+++ bar7b"        NL
755                        "@@ -1,2 +1,2 @@"  NL
756                        "-Aa\r"
757                        "+Bb\n"
758                        " Cc\n",
759                        NULL, pool));
760 
761   SVN_ERR(two_way_diff("foo8", "bar8",
762                        "Aa\n"
763                        "Bb\n"
764                        "Cc\n",
765 
766                        "Xx\n"
767                        "Yy\n",
768 
769                        "--- foo8"         NL
770                        "+++ bar8"         NL
771                        "@@ -1,3 +1,2 @@"  NL
772                        "-Aa\n"
773                        "-Bb\n"
774                        "-Cc\n"
775                        "+Xx\n"
776                        "+Yy\n",
777                        NULL, pool));
778 
779   SVN_ERR(two_way_diff("foo9", "bar9",
780                        "Aa\n"
781                        "Bb\n"
782                        "Cc\n",
783 
784                        "Bb\n",
785 
786                        "--- foo9"       NL
787                        "+++ bar9"       NL
788                        "@@ -1,3 +1 @@"  NL
789                        "-Aa\n"
790                        " Bb\n"
791                        "-Cc\n",
792                        NULL, pool));
793 
794   SVN_ERR(two_way_diff("foo10", "bar10",
795                        "Aa\n"
796                        "Bb\n"
797                        "Cc",
798 
799                        "Aa\n"
800                        "Xx\n"
801                        "Yy\n",
802 
803                        "--- foo10"                     NL
804                        "+++ bar10"                     NL
805                        "@@ -1,3 +1,3 @@"               NL
806                        " Aa\n"
807                        "-Bb\n"
808                        "-Cc"                           NL
809                        "\\ No newline at end of file"  NL
810                        "+Xx\n"
811                        "+Yy\n",
812                        NULL, pool));
813 
814   SVN_ERR(two_way_diff("foo11", "bar11",
815                        "Aa\n"
816                        "Xx\n"
817                        "Yy\n",
818 
819                        "Aa\n"
820                        "Bb\n"
821                        "Cc",
822 
823                        "--- foo11"                     NL
824                        "+++ bar11"                     NL
825                        "@@ -1,3 +1,3 @@"               NL
826                        " Aa\n"
827                        "-Xx\n"
828                        "-Yy\n"
829                        "+Bb\n"
830                        "+Cc"                           NL
831                        "\\ No newline at end of file"  NL,
832                        NULL, pool));
833 
834   SVN_ERR(two_way_diff("foo12", "bar12",
835                        "Aa\n"
836                        "Xx\n"
837                        "Yy",
838 
839                        "Aa\n"
840                        "Bb\n"
841                        "Cc",
842 
843                        "--- foo12"                     NL
844                        "+++ bar12"                     NL
845                        "@@ -1,3 +1,3 @@"               NL
846                        " Aa\n"
847                        "-Xx\n"
848                        "-Yy"                           NL
849                        "\\ No newline at end of file"  NL
850                        "+Bb\n"
851                        "+Cc"                           NL
852                        "\\ No newline at end of file"  NL,
853                        NULL, pool));
854 
855   SVN_ERR(two_way_diff("foo13", "bar13",
856                        "Aa\n"
857                        "Bb\n"
858                        "Cc\n"
859                        "Dd\n"
860                        "Ee\n"
861                        "Ff\n"
862                        "Gg\n",
863 
864                        "Xx\n"
865                        "Aa\n"
866                        "Bb\n"
867                        "Cc\n"
868                        "Dd\n"
869                        "Ee\n"
870                        "Ff\n"
871                        "Gg\n"
872                        "Yy\n",
873 
874                        "--- foo13"        NL
875                        "+++ bar13"        NL
876                        "@@ -1,3 +1,4 @@"  NL
877                        "+Xx\n"
878                        " Aa\n"
879                        " Bb\n"
880                        " Cc\n"
881                        "@@ -5,3 +6,4 @@"  NL
882                        " Ee\n"
883                        " Ff\n"
884                        " Gg\n"
885                        "+Yy\n",
886                        NULL, pool));
887 
888   SVN_ERR(two_way_diff("foo14", "bar14",
889                        "Aa\n"
890                        "Bb\n"
891                        "Cc\n"
892                        "Dd\n"
893                        "Ee\n"
894                        "Ff\n"
895                        "Gg\n",
896 
897                        "Bb\n"
898                        "Aa\n"
899                        "Cc\n"
900                        "Dd\n"
901                        "Ee\n"
902                        "Gg\n"
903                        "Ff\n",
904 
905                        "--- foo14"        NL
906                        "+++ bar14"        NL
907                        "@@ -1,7 +1,7 @@"  NL
908                        "+Bb\n"
909                        " Aa\n"
910                        "-Bb\n"
911                        " Cc\n"
912                        " Dd\n"
913                        " Ee\n"
914                        "+Gg\n"
915                        " Ff\n"
916                        "-Gg\n",
917                        NULL, pool));
918 
919   SVN_ERR(two_way_diff("foo16", "bar16",
920                        "Aa\n"
921                        "\n"
922                        "Cc\n",
923 
924                        "Aa\n"
925                        "Bb\n"
926                        "Cc\n",
927 
928                        "--- foo16"        NL
929                        "+++ bar16"        NL
930                        "@@ -1,3 +1,3 @@"  NL
931                        " Aa\n"
932                        "-\n"
933                        "+Bb\n"
934                        " Cc\n",
935                        NULL, pool));
936 
937   return SVN_NO_ERROR;
938 }
939 
940 
941 static svn_error_t *
test_two_way_unified_suspect(apr_pool_t * pool)942 test_two_way_unified_suspect(apr_pool_t *pool)
943 {
944   SVN_ERR(two_way_diff("foo15a", "bar15a",
945                        "Aa\n"
946                        "Bb\n"
947                        "Cc\n"
948                        "Dd\n"
949                        "Ee\n"
950                        "Ff\n"
951                        "Gg\n"
952                        "Hh\n"
953                        "Ii\n",
954 
955                        "Aa\n"
956                        "Bb\n"
957                        "Cc\n"
958                        "Dd\n"
959                        "Ff\n"
960                        "Gg\n"
961                        "Hh\n"
962                        "Ii\n",
963 
964                        "--- foo15a"       NL
965                        "+++ bar15a"       NL
966                        "@@ -2,7 +2,6 @@"  NL
967                        " Bb\n"
968                        " Cc\n"
969                        " Dd\n"
970                        "-Ee\n"
971                        " Ff\n"
972                        " Gg\n"
973                        " Hh\n",
974                        NULL, pool));
975 
976   SVN_ERR(two_way_diff("foo15b", "bar15b",
977                        "Aa\n"
978                        "Bb\n"
979                        "Cc\n"
980                        "Dd\n"
981                        "Ee\n"
982                        "Ff\n"
983                        "Gg\n"
984                        "Hh\n"
985                        "Ii\n",
986 
987                        "Aa\n"
988                        "Bb\n"
989                        "Cc\n"
990                        "Dd\n"
991                        "Ee\n"
992                        "Xx\n"
993                        "Yy\n"
994                        "Ff\n"
995                        "Gg\n"
996                        "Hh\n"
997                        "Ii\n",
998 
999                        "--- foo15b"       NL
1000                        "+++ bar15b"       NL
1001                        "@@ -3,6 +3,8 @@"  NL
1002                        " Cc\n"
1003                        " Dd\n"
1004                        " Ee\n"
1005                        "+Xx\n"
1006                        "+Yy\n"
1007                        " Ff\n"
1008                        " Gg\n"
1009                        " Hh\n",
1010                        NULL, pool));
1011 
1012   SVN_ERR(two_way_diff("foo15c", "bar15c",
1013                        "Aa\n"
1014                        "Bb\n"
1015                        "Cc\n"
1016                        "Dd\n"
1017                        "Ee\n"
1018                        "Ff\n"
1019                        "Gg\n"
1020                        "Hh\n"
1021                        "Ii\n",
1022 
1023                        "Aa\n"
1024                        "Bb\n"
1025                        "Cc\n"
1026                        "Dd\n"
1027                        "Xx\n"
1028                        "Yy\n"
1029                        "Ff\n"
1030                        "Gg\n"
1031                        "Hh\n"
1032                        "Ii\n",
1033 
1034                        "--- foo15c"       NL
1035                        "+++ bar15c"       NL
1036                        "@@ -2,7 +2,8 @@"  NL
1037                        " Bb\n"
1038                        " Cc\n"
1039                        " Dd\n"
1040                        "-Ee\n"
1041                        "+Xx\n"
1042                        "+Yy\n"
1043                        " Ff\n"
1044                        " Gg\n"
1045                        " Hh\n",
1046                        NULL, pool));
1047 
1048   return SVN_NO_ERROR;
1049 }
1050 
1051 
1052 static svn_error_t *
test_three_way_merge_no_overlap(apr_pool_t * pool)1053 test_three_way_merge_no_overlap(apr_pool_t *pool)
1054 {
1055   svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
1056 
1057   SVN_ERR(three_way_merge("zig1", "zag1", "zog1",
1058                           "Aa\n"
1059                           "Bb\n"
1060                           "Cc\n",
1061 
1062                           "Xx\n"
1063                           "Aa\n"
1064                           "Bb\n"
1065                           "Cc\n",
1066 
1067                           "Aa\n"
1068                           "Bb\n"
1069                           "Cc\n"
1070                           "Yy\n",
1071 
1072                           "Xx\n"
1073                           "Aa\n"
1074                           "Bb\n"
1075                           "Cc\n"
1076                           "Yy\n",
1077                           NULL,
1078                           svn_diff_conflict_display_modified_latest,
1079                           pool));
1080 
1081   SVN_ERR(three_way_merge("zig1a", "zag1a", "zog1a",
1082                           "Aa\r\n"
1083                           "Bb\r\n"
1084                           "Cc\r\n",
1085 
1086                           "Xx\r\n"
1087                           "Aa\r\n"
1088                           "Bb\r\n"
1089                           "Cc\r\n",
1090 
1091                           "Aa\r\n"
1092                           "Bb\r\n"
1093                           "Cc\r\n"
1094                           "Yy\r\n",
1095 
1096                           "Xx\r\n"
1097                           "Aa\r\n"
1098                           "Bb\r\n"
1099                           "Cc\r\n"
1100                           "Yy\r\n",
1101                           NULL,
1102                           svn_diff_conflict_display_modified_latest,
1103                           pool));
1104 
1105   SVN_ERR(three_way_merge("zig1b", "zag1b", "zog1b",
1106                           "Aa\r"
1107                           "Bb\r"
1108                           "Cc\r",
1109 
1110                           "Xx\r"
1111                           "Aa\r"
1112                           "Bb\r"
1113                           "Cc\r",
1114 
1115                           "Aa\r"
1116                           "Bb\r"
1117                           "Cc\r"
1118                           "Yy\r",
1119 
1120                           "Xx\r"
1121                           "Aa\r"
1122                           "Bb\r"
1123                           "Cc\r"
1124                           "Yy\r",
1125                           NULL,
1126                           svn_diff_conflict_display_modified_latest,
1127                           pool));
1128 
1129   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
1130   SVN_ERR(three_way_merge("zig1c", "zag1c", "zog1c",
1131                           "Aa\n"
1132                           "Bb\n"
1133                           "Cc\n",
1134 
1135                           "X x\n"
1136                           "A a\n"
1137                           "B b\n"
1138                           "C c\n",
1139 
1140                           "Aa\n"
1141                           "Bb\n"
1142                           "Cc\n"
1143                           "Yy\n",
1144 
1145                           "X x\n"
1146                           "A a\n"
1147                           "B b\n"
1148                           "C c\n"
1149                           "Yy\n",
1150                           diff_opts,
1151                           svn_diff_conflict_display_modified_latest,
1152                           pool));
1153   diff_opts->ignore_space = svn_diff_file_ignore_space_none;
1154 
1155   SVN_ERR(three_way_merge("zig2", "zag2", "zog2",
1156                           "Aa\n"
1157                           "Bb\n"
1158                           "Cc\n",
1159 
1160                           "Xx\n"
1161                           "Aa\n"
1162                           "Bb\n"
1163                           "Cc\n"
1164                           "Yy\n",
1165 
1166                           "Aa\n"
1167                           "Bb\n"
1168                           "Zz\n"
1169                           "Cc\n",
1170 
1171                           "Xx\n"
1172                           "Aa\n"
1173                           "Bb\n"
1174                           "Zz\n"
1175                           "Cc\n"
1176                           "Yy\n",
1177                           NULL,
1178                           svn_diff_conflict_display_modified_latest,
1179                           pool));
1180 
1181   SVN_ERR(three_way_merge("zig3a", "zag3a", "zog3a",
1182                           "Aa\n"
1183                           "Bb\n"
1184                           "Cc\n",
1185 
1186                           "Aa\n"
1187                           "Bb\n"
1188                           "Cc",
1189 
1190                           "Xx\n"
1191                           "Bb\n"
1192                           "Cc\n",
1193 
1194                           "Xx\n"
1195                           "Bb\n"
1196                           "Cc",
1197                           NULL,
1198                           svn_diff_conflict_display_modified_latest,
1199                           pool));
1200 
1201   SVN_ERR(three_way_merge("zig3b", "zag3b", "zog3b",
1202                           "Aa\n"
1203                           "Bb\n"
1204                           "Cc\n",
1205 
1206                           "Xx\n"
1207                           "Bb\n"
1208                           "Cc\n",
1209 
1210                           "Aa\n"
1211                           "Bb\n"
1212                           "Cc",
1213 
1214                           "Xx\n"
1215                           "Bb\n"
1216                           "Cc",
1217                           NULL,
1218                           svn_diff_conflict_display_modified_latest,
1219                           pool));
1220 
1221   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
1222   diff_opts->ignore_eol_style = TRUE;
1223   SVN_ERR(three_way_merge("zig2c", "zag2c", "zog2c",
1224                           "Aa\n"
1225                           "Bb\n"
1226                           "Cc\n",
1227 
1228                           " Xx\r\n"
1229                           " Aa\r\n"
1230                           " Bb\r\n"
1231                           " Cc\r\n"
1232                           " Yy\r\n",
1233 
1234                           "Aa\n"
1235                           "Bb\n"
1236                           "Zz\n"
1237                           "Cc\n",
1238 
1239                           " Xx\r\n"
1240                           " Aa\r\n"
1241                           " Bb\r\n"
1242                           "Zz\n"
1243                           " Cc\r\n"
1244                           " Yy\r\n",
1245                           diff_opts,
1246                           svn_diff_conflict_display_modified_latest,
1247                           pool));
1248   diff_opts->ignore_space = svn_diff_file_ignore_space_none;
1249   diff_opts->ignore_eol_style = FALSE;
1250 
1251   SVN_ERR(three_way_merge("zig4", "zag4", "zog4",
1252                           "Aa\n"
1253                           "Bb\n"
1254                           "Cc\n"
1255                           "Dd\n"
1256                           "Ee\n"
1257                           "Ff\n"
1258                           "Gg\n"
1259                           "Hh\n"
1260                           "Ii\n",
1261 
1262                           "Aa\n"
1263                           "Bb\n"
1264                           "Cc\n"
1265                           "Dd\n"
1266                           "Ee\n"
1267                           "Ff\n"
1268                           "Yy\n"
1269                           "Zz\n"
1270                           "Hh\n"
1271                           "Ii\n",
1272 
1273                           "Bb\n"
1274                           "Cc\n"
1275                           "Dd\n"
1276                           "Ee\n"
1277                           "Ff\n"
1278                           "Gg\n"
1279                           "Hh\n"
1280                           "Ii\n",
1281 
1282                           "Bb\n"
1283                           "Cc\n"
1284                           "Dd\n"
1285                           "Ee\n"
1286                           "Ff\n"
1287                           "Yy\n"
1288                           "Zz\n"
1289                           "Hh\n"
1290                           "Ii\n",
1291                           NULL,
1292                           svn_diff_conflict_display_modified_latest,
1293                           pool));
1294 
1295   SVN_ERR(three_way_merge("zig5", "zag5", "zog5",
1296                           "Aa\r\n"
1297                           "Bb\n"
1298                           "Cc\n",
1299 
1300                           "Xx\r\n"
1301                           "Aa\r\n"
1302                           "Bb\n"
1303                           "Cc\n",
1304 
1305                           "Aa\r\n"
1306                           "Bb\n"
1307                           "Cc\n"
1308                           "Yy\r\n",
1309 
1310                           "Xx\r\n"
1311                           "Aa\r\n"
1312                           "Bb\n"
1313                           "Cc\n"
1314                           "Yy\r\n",
1315                           NULL,
1316                           svn_diff_conflict_display_modified_latest,
1317                           pool));
1318 
1319   SVN_ERR(three_way_merge("zig6", "zag6", "zog6",
1320                           "AaAaAaAaAaAa\n"
1321                           "Bb\n"
1322                           "Cc\n",
1323 
1324                           "Xx\n"
1325                           "Bb\n"
1326                           "Cc\n",
1327 
1328                           "AaAaAaAaAaAa\n"
1329                           "Bb\n"
1330                           "CcCcCcCcCcCc\n"
1331                           "Yy\n",
1332 
1333                           "Xx\n"
1334                           "Bb\n"
1335                           "CcCcCcCcCcCc\n"
1336                           "Yy\n",
1337                           NULL,
1338                           svn_diff_conflict_display_modified_latest,
1339                           pool));
1340 
1341   SVN_ERR(three_way_merge("zig7", "zag7", "zog7",
1342                           "Aa\n"
1343                           "Bb\n"
1344                           "Cc\n",
1345 
1346                           "Aa\n"
1347                           "Bb\n"
1348                           "Cc\n"
1349                           "Dd",
1350 
1351                           "Aa\n"
1352                           "Bb\n"
1353                           "Cc\n",
1354 
1355                           "Aa\n"
1356                           "Bb\n"
1357                           "Cc\n"
1358                           "Dd",
1359                           NULL,
1360                           svn_diff_conflict_display_modified_latest,
1361                           pool));
1362 
1363   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
1364   diff_opts->ignore_eol_style = FALSE;
1365   SVN_ERR(three_way_merge("zig8", "zag8", "zog8",
1366                           "Aa\n"
1367                           "Bb\n"
1368                           "Cc\n",
1369 
1370                           "   Aa\n"
1371                           "B b\n"
1372                           "C c\n",
1373 
1374                           "A a\n"
1375                           "Bb \n"
1376                           " Cc\n"
1377                           "New line in zog8\n",
1378 
1379                           "   Aa\n"
1380                           "B b\n"
1381                           "C c\n"
1382                           "New line in zog8\n",
1383                           diff_opts,
1384                           svn_diff_conflict_display_modified_latest,
1385                           pool));
1386 
1387   return SVN_NO_ERROR;
1388 }
1389 
1390 
1391 static svn_error_t *
test_three_way_merge_with_overlap(apr_pool_t * pool)1392 test_three_way_merge_with_overlap(apr_pool_t *pool)
1393 {
1394   SVN_ERR(three_way_merge("splish1", "splash1", "splosh1",
1395                           "Aa\n"
1396                           "Bb\n"
1397                           "Cc\n"
1398                           "Dd\n"
1399                           "Ee\n",
1400 
1401                           "Aa\n"
1402                           "Xx\n"
1403                           "Bb\n"
1404                           "Cc\n"
1405                           "Yy\n"
1406                           "Ee\n",
1407 
1408                           "Aa\n"
1409                           "Bb\n"
1410                           "Cc\n"
1411                           "Yy\n"
1412                           "Ee\n"
1413                           "Zz\n",
1414 
1415                           "Aa\n"
1416                           "Xx\n"
1417                           "Bb\n"
1418                           "Cc\n"
1419                           "Yy\n"
1420                           "Ee\n"
1421                           "Zz\n",
1422                           NULL,
1423                           svn_diff_conflict_display_modified_latest,
1424                           pool));
1425 
1426   SVN_ERR(three_way_merge("splish2", "splash2", "splosh2",
1427                           "Aa\n"
1428                           "Bb\n"
1429                           "Cc\n"
1430                           "Dd\n"
1431                           "Ee\n"
1432                           "Ff\n",
1433 
1434                           "Aa\n"
1435                           "Yy\n"
1436                           "Zz\n"
1437                           "Dd\n"
1438                           "Pp\n"
1439                           "Qq\n"
1440                           "Ff\n",
1441 
1442                           "Pp\n"
1443                           "Qq\n"
1444                           "Aa\n"
1445                           "Bb\n"
1446                           "Cc\n"
1447                           "Dd\n"
1448                           "Pp\n"
1449                           "Qq\n"
1450                           "Ff\n"
1451                           "Pp\n"
1452                           "Qq\n",
1453 
1454                           "Pp\n"
1455                           "Qq\n"
1456                           "Aa\n"
1457                           "Yy\n"
1458                           "Zz\n"
1459                           "Dd\n"
1460                           "Pp\n"
1461                           "Qq\n"
1462                           "Ff\n"
1463                           "Pp\n"
1464                           "Qq\n",
1465                           NULL,
1466                           svn_diff_conflict_display_modified_latest,
1467                           pool));
1468 
1469   SVN_ERR(three_way_merge("splish3", "splash3", "splosh3",
1470                           "Aa\n"
1471                           "Bb\n"
1472                           "Cc\n",
1473 
1474                           "Xx\n"
1475                           "Aa\n"
1476                           "Bb\n"
1477                           "Cc",
1478 
1479                           "Aa\n"
1480                           "Xx\n"
1481                           "Bb\n"
1482                           "Cc",
1483 
1484                           "Xx\n"
1485                           "Aa\n"
1486                           "Xx\n"
1487                           "Bb\n"
1488                           "Cc",
1489                           NULL,
1490                           svn_diff_conflict_display_modified_latest,
1491                           pool));
1492 
1493   SVN_ERR(three_way_merge("splish4", "splash4", "splosh4",
1494                           "Aa\n"
1495                           "Bb\n"
1496                           "Cc\n"
1497                           "Dd\n"
1498                           "Ee\n"
1499                           "Ff\n"
1500                           "Gg\n"
1501                           "Hh\n",
1502 
1503                           "Aa\n"
1504                           "Ff\n"
1505                           "Gg\n"
1506                           "Hh\n"
1507                           "Bb\n"
1508                           "Cc\n"
1509                           "Xx\n"
1510                           "Dd\n"
1511                           "Ee\n"
1512                           "Yy\n"
1513                           "Ff\n"
1514                           "Gg\n"
1515                           "Hh\n",
1516 
1517                           "Aa\n"
1518                           "Bb\n"
1519                           "Cc\n"
1520                           "Xx\n"
1521                           "Dd\n"
1522                           "Ee\n"
1523                           "Ff\n"
1524                           "Gg\n"
1525                           "Zz\n"
1526                           "Hh\n",
1527 
1528                           "Aa\n"
1529                           "Ff\n"
1530                           "Gg\n"
1531                           "Hh\n"
1532                           "Bb\n"
1533                           "Cc\n"
1534                           "Xx\n"
1535                           "Dd\n"
1536                           "Ee\n"
1537                           "Yy\n"
1538                           "Ff\n"
1539                           "Gg\n"
1540                           "Zz\n"
1541                           "Hh\n",
1542                           NULL,
1543                           svn_diff_conflict_display_modified_latest,
1544                           pool));
1545 
1546   return SVN_NO_ERROR;
1547 }
1548 
1549 
1550 static svn_error_t *
test_three_way_merge_with_conflict(apr_pool_t * pool)1551 test_three_way_merge_with_conflict(apr_pool_t *pool)
1552 {
1553   SVN_ERR(three_way_merge("dig1", "dug1", "dag1",
1554                           "Aa\n"
1555                           "Bb\n"
1556                           "Cc\n",
1557 
1558                           "",
1559 
1560                           "",
1561 
1562                           "",
1563                           NULL,
1564                           svn_diff_conflict_display_modified_latest,
1565                           pool));
1566 
1567   SVN_ERR(three_way_merge("dig2", "dug2", "dag2",
1568                           "Aa\n"
1569                           "Bb\n"
1570                           "Cc\n",
1571 
1572                           "Aa\n"
1573                           "Bb\n"
1574                           "Cc\n"
1575                           "Dd\n"
1576                           "Ee\n"
1577                           "Ff\n",
1578 
1579                           "",
1580 
1581                           "<<<<<<< dug2\n"
1582                           "Aa\n"
1583                           "Bb\n"
1584                           "Cc\n"
1585                           "Dd\n"
1586                           "Ee\n"
1587                           "Ff\n"
1588                           "=======\n"
1589                           ">>>>>>> dag2\n",
1590                           NULL,
1591                           svn_diff_conflict_display_modified_latest,
1592                           pool));
1593 
1594   SVN_ERR(three_way_merge("dig2a", "dug2a", "dag2a",
1595                           "Aa\r\n"
1596                           "Bb\r\n"
1597                           "Cc\r\n",
1598 
1599                           "Aa\r\n"
1600                           "Bb\r\n"
1601                           "Cc\r\n"
1602                           "Dd\r\n"
1603                           "Ee\r\n"
1604                           "Ff\r\n",
1605 
1606                           "",
1607 
1608                           "<<<<<<< dug2a\r\n"
1609                           "Aa\r\n"
1610                           "Bb\r\n"
1611                           "Cc\r\n"
1612                           "Dd\r\n"
1613                           "Ee\r\n"
1614                           "Ff\r\n"
1615                           "=======\r\n"
1616                           ">>>>>>> dag2a\r\n",
1617                           NULL,
1618                           svn_diff_conflict_display_modified_latest,
1619                           pool));
1620 
1621   SVN_ERR(three_way_merge("dig2b", "dug2b", "dag2b",
1622                           "Aa\n"
1623                           "Bb\n"
1624                           "Cc\n",
1625 
1626                           "Aa\r"
1627                           "Bb\r"
1628                           "Cc\r"
1629                           "Dd\r"
1630                           "Ee\r"
1631                           "Ff\r",
1632 
1633                           "",
1634 
1635                           "<<<<<<< dug2b\r"
1636                           "Aa\r"
1637                           "Bb\r"
1638                           "Cc\r"
1639                           "Dd\r"
1640                           "Ee\r"
1641                           "Ff\r"
1642                           "=======\r"
1643                           ">>>>>>> dag2b\r",
1644                           NULL,
1645                           svn_diff_conflict_display_modified_latest,
1646                           pool));
1647 
1648   SVN_ERR(three_way_merge("dig3", "dug3", "dag3",
1649                           "Aa\n"
1650                           "Bb\n"
1651                           "Cc\n",
1652 
1653                           "Aa\n"
1654                           "Bb\n"
1655                           "Cc\n"
1656                           "Dd\n"
1657                           "Ee\n"
1658                           "Ff\n",
1659 
1660                           "Aa\n"
1661                           "Bb\n",
1662 
1663                           "Aa\n"
1664                           "Bb\n"
1665                           "<<<<<<< dug3\n"
1666                           "Cc\n"
1667                           "Dd\n"
1668                           "Ee\n"
1669                           "Ff\n"
1670                           "=======\n"
1671                           ">>>>>>> dag3\n",
1672                           NULL,
1673                           svn_diff_conflict_display_modified_latest,
1674                           pool));
1675 
1676   SVN_ERR(three_way_merge("dig4", "dug4", "dag4",
1677                           "Aa\n"
1678                           "Bb\n"
1679                           "Cc\n",
1680 
1681                           "Aa\n"
1682                           "Bb\n"
1683                           "Cc\n"
1684                           "Dd",
1685 
1686                           "Aa\n"
1687                           "Bb\n"
1688                           "Cc\n"
1689                           "Ee",
1690 
1691                           "Aa\n"
1692                           "Bb\n"
1693                           "Cc\n"
1694                           "<<<<<<< dug4\n"
1695                           "Dd=======\n"
1696                           "Ee>>>>>>> dag4\n",
1697                           NULL,
1698                           svn_diff_conflict_display_modified_latest,
1699                           pool));
1700 
1701   return SVN_NO_ERROR;
1702 }
1703 
1704 
1705 static svn_error_t *
test_three_way_merge_conflict_styles(apr_pool_t * pool)1706 test_three_way_merge_conflict_styles(apr_pool_t *pool)
1707 {
1708   static const char *original =
1709     "a\n"
1710     "b\n"
1711     "c\n"
1712     "d\n"
1713     "e\n"
1714     "f\n"
1715     "g\n"
1716     "h\n"
1717     "i\n"
1718     "j\n"
1719     "k\n"
1720     "l\n"
1721     "m\n"
1722     "n\n"
1723     "o\n"
1724     "p\n"
1725     "q\n"
1726     "r\n"
1727     "s\n"
1728     "t\n"
1729     "u\n"
1730     "v\n"
1731     "w\n"
1732     "x\n"
1733     "y\n"
1734     "z\n"
1735     ;
1736   static const char *modified =
1737     "A\n"
1738     "b\n"
1739     "c\n"
1740     "d\n"
1741     "e\n"
1742     "f\n"
1743     "g\n"
1744     "h\n"
1745     "iMOD\n"
1746     "j\n"
1747     "k\n"
1748     "l\n"
1749     "m\n"
1750     "N\n"
1751     "O\n"
1752     "hello\n"
1753     "world\n"
1754     "yay\n"
1755     "P\n"
1756     "Q\n"
1757     "r\n"
1758     "s\n"
1759     "t\n"
1760     "u\n"
1761     "v\n"
1762     "w\n"
1763     "x\n"
1764     "y\n"
1765     "z\n"
1766     ;
1767   static const char *latest =
1768     "a\n"
1769     "b\n"
1770     "c\n"
1771     "d\n"
1772     "e\n"
1773     "f\n"
1774     "g\n"
1775     "h\n"
1776     "i\n"
1777     "j\n"
1778     "k1\n"
1779     "l2\n"
1780     "m3\n"
1781     "n4\n"
1782     "o5\n"
1783     "hello\n"
1784     "world\n"
1785     "yay\n"
1786     "p\n"
1787     "q\n"
1788     "r\n"
1789     "sLAT\n"
1790     "t\n"
1791     "u\n"
1792     "v\n"
1793     "w\n"
1794     "x\n"
1795     "y\n"
1796     "Z\n"
1797     ;
1798   /* So, 'modified' capitalized N through Q; 'latest' added numbers to
1799      'k' through 'o'; and they both inserted "hello world yay" in the
1800      middle.  Also, there are non-conflicting changes to the first and
1801      last lines. */
1802 
1803   SVN_ERR(three_way_merge("style-normal1", "style-normal2", "style-normal3",
1804                           original, modified, latest,
1805                           "A\n"
1806                           "b\n"
1807                           "c\n"
1808                           "d\n"
1809                           "e\n"
1810                           "f\n"
1811                           "g\n"
1812                           "h\n"
1813                           "iMOD\n"
1814                           "j\n"
1815                           "<<<<<<< style-normal2\n"
1816                           "k\n"
1817                           "l\n"
1818                           "m\n"
1819                           "N\n"
1820                           "O\n"
1821                           "hello\n"
1822                           "world\n"
1823                           "yay\n"
1824                           "P\n"
1825                           "Q\n"
1826                           "=======\n"
1827                           "k1\n"
1828                           "l2\n"
1829                           "m3\n"
1830                           "n4\n"
1831                           "o5\n"
1832                           "hello\n"
1833                           "world\n"
1834                           "yay\n"
1835                           "p\n"
1836                           "q\n"
1837                           ">>>>>>> style-normal3\n"
1838                           "r\n"
1839                           "sLAT\n"
1840                           "t\n"
1841                           "u\n"
1842                           "v\n"
1843                           "w\n"
1844                           "x\n"
1845                           "y\n"
1846                           "Z\n",
1847                           NULL,
1848                           svn_diff_conflict_display_modified_latest,
1849                           pool));
1850 
1851   SVN_ERR(three_way_merge("style-resolved1", "style-resolved2",
1852                           "style-resolved3",
1853                           original, modified, latest,
1854                           "A\n"
1855                           "b\n"
1856                           "c\n"
1857                           "d\n"
1858                           "e\n"
1859                           "f\n"
1860                           "g\n"
1861                           "h\n"
1862                           "iMOD\n"
1863                           "j\n"
1864                           "<<<<<<< style-resolved2\n"
1865                           "k\n"
1866                           "l\n"
1867                           "m\n"
1868                           "N\n"
1869                           "O\n"
1870                           "=======\n"
1871                           "k1\n"
1872                           "l2\n"
1873                           "m3\n"
1874                           "n4\n"
1875                           "o5\n"
1876                           ">>>>>>> style-resolved3\n"
1877                           "hello\n"
1878                           "world\n"
1879                           "yay\n"
1880                           "<<<<<<< style-resolved2\n"
1881                           "P\n"
1882                           "Q\n"
1883                           "=======\n"
1884                           "p\n"
1885                           "q\n"
1886                           ">>>>>>> style-resolved3\n"
1887                           "r\n"
1888                           "sLAT\n"
1889                           "t\n"
1890                           "u\n"
1891                           "v\n"
1892                           "w\n"
1893                           "x\n"
1894                           "y\n"
1895                           "Z\n",
1896                           NULL,
1897                           svn_diff_conflict_display_resolved_modified_latest,
1898                           pool));
1899 
1900   SVN_ERR(three_way_merge("style-three1", "style-three2", "style-three3",
1901                           original, modified, latest,
1902                           "A\n"
1903                           "b\n"
1904                           "c\n"
1905                           "d\n"
1906                           "e\n"
1907                           "f\n"
1908                           "g\n"
1909                           "h\n"
1910                           "iMOD\n"
1911                           "j\n"
1912                           "<<<<<<< style-three2\n"
1913                           "k\n"
1914                           "l\n"
1915                           "m\n"
1916                           "N\n"
1917                           "O\n"
1918                           "hello\n"
1919                           "world\n"
1920                           "yay\n"
1921                           "P\n"
1922                           "Q\n"
1923                           "||||||| style-three1\n"
1924                           "k\n"
1925                           "l\n"
1926                           "m\n"
1927                           "n\n"
1928                           "o\n"
1929                           "p\n"
1930                           "q\n"
1931                           "=======\n"
1932                           "k1\n"
1933                           "l2\n"
1934                           "m3\n"
1935                           "n4\n"
1936                           "o5\n"
1937                           "hello\n"
1938                           "world\n"
1939                           "yay\n"
1940                           "p\n"
1941                           "q\n"
1942                           ">>>>>>> style-three3\n"
1943                           "r\n"
1944                           "sLAT\n"
1945                           "t\n"
1946                           "u\n"
1947                           "v\n"
1948                           "w\n"
1949                           "x\n"
1950                           "y\n"
1951                           "Z\n",
1952                           NULL,
1953                           svn_diff_conflict_display_modified_original_latest,
1954                           pool));
1955 
1956   SVN_ERR(three_way_merge("style-only1", "style-only2", "style-only3",
1957                           original, modified, latest,
1958                           "@@\n"
1959                           "h\n"
1960                           "iMOD\n"
1961                           "j\n"
1962                           "<<<<<<< style-only2 (11,10)\n"
1963                           "k\n"
1964                           "l\n"
1965                           "m\n"
1966                           "N\n"
1967                           "O\n"
1968                           "hello\n"
1969                           "world\n"
1970                           "yay\n"
1971                           "P\n"
1972                           "Q\n"
1973                           "||||||| style-only1 (11,7)\n"
1974                           "k\n"
1975                           "l\n"
1976                           "m\n"
1977                           "n\n"
1978                           "o\n"
1979                           "p\n"
1980                           "q\n"
1981                           "=======\n"
1982                           "k1\n"
1983                           "l2\n"
1984                           "m3\n"
1985                           "n4\n"
1986                           "o5\n"
1987                           "hello\n"
1988                           "world\n"
1989                           "yay\n"
1990                           "p\n"
1991                           "q\n"
1992                           ">>>>>>> style-only3 (11,10)\n"
1993                           "r\n"
1994                           "sLAT\n"
1995                           "t\n",
1996                           NULL,
1997                           svn_diff_conflict_display_only_conflicts,
1998                           pool));
1999 
2000   SVN_ERR(three_way_merge("style-mod1", "style-mod2", "style-mod3",
2001                           original, modified, latest,
2002                           "A\n"
2003                           "b\n"
2004                           "c\n"
2005                           "d\n"
2006                           "e\n"
2007                           "f\n"
2008                           "g\n"
2009                           "h\n"
2010                           "iMOD\n"
2011                           "j\n"
2012                           "k\n"
2013                           "l\n"
2014                           "m\n"
2015                           "N\n"
2016                           "O\n"
2017                           "hello\n"
2018                           "world\n"
2019                           "yay\n"
2020                           "P\n"
2021                           "Q\n"
2022                           "r\n"
2023                           "sLAT\n"
2024                           "t\n"
2025                           "u\n"
2026                           "v\n"
2027                           "w\n"
2028                           "x\n"
2029                           "y\n"
2030                           "Z\n",
2031                           NULL,
2032                           svn_diff_conflict_display_modified,
2033                           pool));
2034 
2035   SVN_ERR(three_way_merge("style-latest1", "style-latest2", "style-latest3",
2036                           original, modified, latest,
2037                           "A\n"
2038                           "b\n"
2039                           "c\n"
2040                           "d\n"
2041                           "e\n"
2042                           "f\n"
2043                           "g\n"
2044                           "h\n"
2045                           "iMOD\n"
2046                           "j\n"
2047                           "k1\n"
2048                           "l2\n"
2049                           "m3\n"
2050                           "n4\n"
2051                           "o5\n"
2052                           "hello\n"
2053                           "world\n"
2054                           "yay\n"
2055                           "p\n"
2056                           "q\n"
2057                           "r\n"
2058                           "sLAT\n"
2059                           "t\n"
2060                           "u\n"
2061                           "v\n"
2062                           "w\n"
2063                           "x\n"
2064                           "y\n"
2065                           "Z\n",
2066                           NULL,
2067                           svn_diff_conflict_display_latest,
2068                           pool));
2069 
2070   return SVN_NO_ERROR;
2071 }
2072 
2073 
2074 #define MAKE_STRING(cstr) { (cstr), sizeof((cstr))-1 }
2075 
2076 static svn_error_t *
test_diff4(apr_pool_t * pool)2077 test_diff4(apr_pool_t *pool)
2078 {
2079   svn_diff_t *diff;
2080   svn_stream_t *actual, *expected;
2081   svn_boolean_t same;
2082   static svn_string_t B2 = MAKE_STRING(
2083     "int main (int argc, char **argv)\n"
2084     "{\n"
2085     "  /* line minus-five of context */\n"
2086     "  /* line minus-four of context */\n"
2087     "  /* line minus-three of context */\n"
2088     "  /* line -1 of context */\n"
2089     "  printf (\"Hello, world!\\n\");\n"
2090     "  /* newly inserted line of context */\n"
2091     "  /* line plus-one of context */\n"
2092     "  /* line plus-two of context */\n"
2093     "  /* line plus-three of context */\n"
2094     "  /* line plus-four of context */\n"
2095     "  /* line plus-five of context */\n"
2096     "}\n");
2097   static svn_string_t B2new = MAKE_STRING(
2098     "int main (int argc, char **argv)\n"
2099     "{\n"
2100     "  /* line minus-five of context */\n"
2101     "  /* line minus-four of context */\n"
2102     "  /* line minus-three of context */\n"
2103     "  /* line -1 of context */\n"
2104     "  printf (\"Good-bye, cruel world!\\n\");\n"
2105     "  /* newly inserted line of context */\n"
2106     "  /* line plus-one of context */\n"
2107     "  /* line plus-two of context */\n"
2108     "  /* line plus-three of context */\n"
2109     "  /* line plus-four of context */\n"
2110     "  /* line plus-five of context */\n"
2111     "}\n");
2112   static svn_string_t T1 = MAKE_STRING(
2113     "int main (int argc, char **argv)\n"
2114     "{\n"
2115     "  /* line minus-five of context */\n"
2116     "  /* line minus-four of context */\n"
2117     "  /* line minus-three of context */\n"
2118     "  /* line minus-two of context */\n"
2119     "  /* line minus-one of context */\n"
2120     "  printf (\"Hello, world!\\n\");\n"
2121     "  /* line plus-one of context */\n"
2122     "  /* line plus-two of context */\n"
2123     "  /* line plus-three of context */\n"
2124     "  /* line plus-four of context */\n"
2125     "  /* line plus-five of context */\n"
2126     "}\n");
2127   static svn_string_t T2 = MAKE_STRING(
2128     "#include <stdio.h>\n"
2129     "\n"
2130     "int main (int argc, char **argv)\n"
2131     "{\n"
2132     "  /* line minus-five of context */\n"
2133     "  /* line minus-four of context */\n"
2134     "  /* line minus-three of context */\n"
2135     "  /* line minus-two of context */\n"
2136     "  /* line minus-one of context */\n"
2137     "  printf (\"Hello, world!\\n\");\n"
2138     "  /* line plus-one of context */\n"
2139     "  /* line plus-two of context */\n"
2140     "  /* line plus-three of context */\n"
2141     "  /* line plus-four of context */\n"
2142     "  /* line plus-five of context */\n"
2143     "}\n");
2144   static svn_string_t T3 = MAKE_STRING(
2145     "#include <stdio.h>\n"
2146     "\n"
2147     "int main (int argc, char **argv)\n"
2148     "{\n"
2149     "  /* line minus-five of context */\n"
2150     "  /* line minus-four of context */\n"
2151     "  /* line minus-three of context */\n"
2152     "  /* line minus-two of context */\n"
2153     "  /* line minus-one of context */\n"
2154     "  printf (\"Good-bye, cruel world!\\n\");\n"
2155     "  /* line plus-one of context */\n"
2156     "  /* line plus-two of context */\n"
2157     "  /* line plus-three of context */\n"
2158     "  /* line plus-four of context */\n"
2159     "  /* line plus-five of context */\n"
2160     "}\n");
2161 
2162   const char *B2_path = svn_test_data_path("B2", pool);
2163   const char *T1_path = svn_test_data_path("T1", pool);
2164   const char *T2_path = svn_test_data_path("T2", pool);
2165   const char *T3_path = svn_test_data_path("T3", pool);
2166 
2167   SVN_ERR(make_file(B2_path, B2.data, pool));
2168   SVN_ERR(make_file(T1_path, T1.data, pool));
2169   SVN_ERR(make_file(T2_path, T2.data, pool));
2170   SVN_ERR(make_file(T3_path, T3.data, pool));
2171 
2172   /* Usage: tools/diff/diff4 <mine> <older> <yours> <ancestor> */
2173   /* tools/diff/diff4 B2 T2 T3 T1 > B2new */
2174   SVN_ERR(svn_diff_file_diff4(&diff, T2_path, B2_path, T3_path, T1_path, pool));
2175 
2176   /* Sanity. */
2177   SVN_TEST_ASSERT(! svn_diff_contains_conflicts(diff));
2178   SVN_TEST_ASSERT(svn_diff_contains_diffs(diff));
2179 
2180   /* Comparison. */
2181   expected = svn_stream_from_string(&B2new, pool);
2182 
2183   actual = svn_stream_from_stringbuf(
2184              svn_stringbuf_create_ensure(417, pool), /* 417 == wc -c < B2new */
2185              pool);
2186   SVN_ERR(svn_diff_file_output_merge(actual, diff,
2187                                      T2_path, B2_path, T3_path,
2188                                      NULL, NULL, NULL, NULL,
2189                                      FALSE,
2190                                      FALSE,
2191                                      pool));
2192   SVN_ERR(svn_stream_contents_same2(&same, actual, expected, pool));
2193   SVN_TEST_ASSERT(same);
2194 
2195   return SVN_NO_ERROR;
2196 }
2197 
2198 
2199 static svn_error_t *
random_trivial_merge(apr_pool_t * pool)2200 random_trivial_merge(apr_pool_t *pool)
2201 {
2202   int i;
2203   apr_pool_t *subpool = svn_pool_create(pool);
2204 
2205   const char *base_filename1 = "trivial1";
2206   const char *base_filename2 = "trivial2";
2207 
2208   const char *filename1 = svn_test_data_path(base_filename1, pool);
2209   const char *filename2 = svn_test_data_path(base_filename2, pool);
2210 
2211   seed_val();
2212 
2213   for (i = 0; i < 5; ++i)
2214     {
2215       int min_lines = 1000;
2216       int max_lines = 1100;
2217       int var_lines = 50;
2218       int block_lines = 10;
2219       svn_stringbuf_t *contents1, *contents2;
2220 
2221       SVN_ERR(make_random_file(filename1,
2222                                min_lines, max_lines, var_lines, block_lines,
2223                                i % 3, subpool));
2224       SVN_ERR(make_random_file(filename2,
2225                                min_lines, max_lines, var_lines, block_lines,
2226                                i % 2, subpool));
2227 
2228       SVN_ERR(svn_stringbuf_from_file2(&contents1, filename1, subpool));
2229       SVN_ERR(svn_stringbuf_from_file2(&contents2, filename2, subpool));
2230 
2231       SVN_ERR(three_way_merge(base_filename1, base_filename2, base_filename1,
2232                               contents1->data, contents2->data,
2233                               contents1->data, contents2->data, NULL,
2234                               svn_diff_conflict_display_modified_latest,
2235                               subpool));
2236       SVN_ERR(three_way_merge(base_filename2, base_filename1, base_filename2,
2237                               contents2->data, contents1->data,
2238                               contents2->data, contents1->data, NULL,
2239                               svn_diff_conflict_display_modified_latest,
2240                               subpool));
2241       svn_pool_clear(subpool);
2242     }
2243   svn_pool_destroy(subpool);
2244 
2245   return SVN_NO_ERROR;
2246 }
2247 
2248 
2249 /* The "original" file has a number of distinct lines.  We generate two
2250    random modifications by selecting two subsets of the original lines and
2251    for each selected line either adding an additional line, replacing the
2252    line, or deleting the line.  The two subsets are chosen so that each
2253    selected line is distinct and no two selected lines are adjacent. This
2254    means the two sets of changes should merge without conflict.  */
2255 static svn_error_t *
random_three_way_merge(apr_pool_t * pool)2256 random_three_way_merge(apr_pool_t *pool)
2257 {
2258   int i;
2259   apr_pool_t *subpool = svn_pool_create(pool);
2260 
2261   const char *base_filename1 = "original";
2262   const char *base_filename2 = "modified1";
2263   const char *base_filename3 = "modified2";
2264   const char *base_filename4 = "combined";
2265 
2266   const char *filename1 = svn_test_data_path(base_filename1, pool);
2267   const char *filename2 = svn_test_data_path(base_filename2, pool);
2268   const char *filename3 = svn_test_data_path(base_filename3, pool);
2269   const char *filename4 = svn_test_data_path(base_filename4, pool);
2270 
2271   seed_val();
2272 
2273   for (i = 0; i < 20; ++i)
2274     {
2275       svn_stringbuf_t *original, *modified1, *modified2, *combined;
2276       /* Pick NUM_LINES large enough so that the 'strip identical suffix' code
2277          gets triggered with reasonable probability.  (Currently it ignores
2278          50 lines or more, and empirically N=4000 suffices to trigger that
2279          behaviour most of the time.) */
2280       int num_lines = 4000, num_src = 10, num_dst = 10;
2281       svn_boolean_t *lines = apr_pcalloc(subpool, sizeof(*lines) * num_lines);
2282       struct random_mod *src_lines = apr_palloc(subpool,
2283                                                 sizeof(*src_lines) * num_src);
2284       struct random_mod *dst_lines = apr_palloc(subpool,
2285                                                 sizeof(*dst_lines) * num_dst);
2286       struct random_mod *mrg_lines = apr_palloc(subpool,
2287                                                 (sizeof(*mrg_lines)
2288                                                  * (num_src + num_dst)));
2289 
2290       select_lines(src_lines, num_src, lines, num_lines);
2291       select_lines(dst_lines, num_dst, lines, num_lines);
2292       memcpy(mrg_lines, src_lines, sizeof(*mrg_lines) * num_src);
2293       memcpy(mrg_lines + num_src, dst_lines, sizeof(*mrg_lines) * num_dst);
2294 
2295       SVN_ERR(make_random_merge_file(filename1, num_lines, NULL, 0, pool));
2296       SVN_ERR(make_random_merge_file(filename2, num_lines, src_lines, num_src,
2297                                      pool));
2298       SVN_ERR(make_random_merge_file(filename3, num_lines, dst_lines, num_dst,
2299                                      pool));
2300       SVN_ERR(make_random_merge_file(filename4, num_lines, mrg_lines,
2301                                      num_src + num_dst, pool));
2302 
2303       SVN_ERR(svn_stringbuf_from_file2(&original, filename1, pool));
2304       SVN_ERR(svn_stringbuf_from_file2(&modified1, filename2, pool));
2305       SVN_ERR(svn_stringbuf_from_file2(&modified2, filename3, pool));
2306       SVN_ERR(svn_stringbuf_from_file2(&combined, filename4, pool));
2307 
2308       SVN_ERR(three_way_merge(base_filename1, base_filename2, base_filename3,
2309                               original->data, modified1->data,
2310                               modified2->data, combined->data, NULL,
2311                               svn_diff_conflict_display_modified_latest,
2312                               subpool));
2313       SVN_ERR(three_way_merge(base_filename1, base_filename3, base_filename2,
2314                               original->data, modified2->data,
2315                               modified1->data, combined->data, NULL,
2316                               svn_diff_conflict_display_modified_latest,
2317                               subpool));
2318 
2319       SVN_ERR(svn_io_remove_file2(filename4, TRUE, pool));
2320 
2321       svn_pool_clear(subpool);
2322     }
2323   svn_pool_destroy(subpool);
2324 
2325   return SVN_NO_ERROR;
2326 }
2327 
2328 /* This is similar to random_three_way_merge above, except this time half
2329    of the original-to-modified1 changes are already present in modified2
2330    (or, equivalently, half the original-to-modified2 changes are already
2331    present in modified1).  Since the overlapping changes match exactly the
2332    merge should work without a conflict. */
2333 static svn_error_t *
merge_with_part_already_present(apr_pool_t * pool)2334 merge_with_part_already_present(apr_pool_t *pool)
2335 {
2336   int i;
2337   apr_pool_t *subpool = svn_pool_create(pool);
2338 
2339   const char *base_filename1 = "pap-original";
2340   const char *base_filename2 = "pap-modified1";
2341   const char *base_filename3 = "pap-modified2";
2342   const char *base_filename4 = "pap-combined";
2343 
2344   const char *filename1 = svn_test_data_path(base_filename1, pool);
2345   const char *filename2 = svn_test_data_path(base_filename2, pool);
2346   const char *filename3 = svn_test_data_path(base_filename3, pool);
2347   const char *filename4 = svn_test_data_path(base_filename4, pool);
2348 
2349   seed_val();
2350 
2351   for (i = 0; i < 20; ++i)
2352     {
2353       svn_stringbuf_t *original, *modified1, *modified2, *combined;
2354       int num_lines = 200, num_src = 20, num_dst = 20;
2355       svn_boolean_t *lines = apr_pcalloc(subpool, sizeof(*lines) * num_lines);
2356       struct random_mod *src_lines = apr_palloc(subpool,
2357                                                 sizeof(*src_lines) * num_src);
2358       struct random_mod *dst_lines = apr_palloc(subpool,
2359                                                 sizeof(*dst_lines) * num_dst);
2360       struct random_mod *mrg_lines = apr_palloc(subpool,
2361                                                 (sizeof(*mrg_lines)
2362                                                  * (num_src + num_dst / 2)));
2363 
2364       select_lines(src_lines, num_src, lines, num_lines);
2365       /* Select half the destination changes at random */
2366       select_lines(dst_lines, num_dst / 2, lines, num_lines);
2367       /* Copy the other half from the source changes */
2368       memcpy(dst_lines + num_dst / 2, src_lines,
2369              sizeof(*dst_lines) * (num_dst - num_dst / 2));
2370       memcpy(mrg_lines, src_lines, sizeof(*mrg_lines) * num_src);
2371       memcpy(mrg_lines + num_src, dst_lines,
2372              sizeof(*mrg_lines) * num_dst / 2);
2373 
2374       SVN_ERR(make_random_merge_file(filename1, num_lines, NULL, 0, pool));
2375       SVN_ERR(make_random_merge_file(filename2, num_lines, src_lines, num_src,
2376                                      pool));
2377       SVN_ERR(make_random_merge_file(filename3, num_lines, dst_lines, num_dst,
2378                                      pool));
2379       SVN_ERR(make_random_merge_file(filename4, num_lines, mrg_lines,
2380                                      num_src + num_dst / 2, pool));
2381 
2382       SVN_ERR(svn_stringbuf_from_file2(&original, filename1, pool));
2383       SVN_ERR(svn_stringbuf_from_file2(&modified1, filename2, pool));
2384       SVN_ERR(svn_stringbuf_from_file2(&modified2, filename3, pool));
2385       SVN_ERR(svn_stringbuf_from_file2(&combined, filename4, pool));
2386 
2387       SVN_ERR(three_way_merge(base_filename1, base_filename2, base_filename3,
2388                               original->data, modified1->data,
2389                               modified2->data, combined->data, NULL,
2390                               svn_diff_conflict_display_modified_latest,
2391                               subpool));
2392       SVN_ERR(three_way_merge(base_filename1, base_filename3, base_filename2,
2393                               original->data, modified2->data,
2394                               modified1->data, combined->data, NULL,
2395                               svn_diff_conflict_display_modified_latest,
2396                               subpool));
2397 
2398       SVN_ERR(svn_io_remove_file2(filename4, TRUE, pool));
2399 
2400       svn_pool_clear(subpool);
2401     }
2402   svn_pool_destroy(subpool);
2403 
2404   return SVN_NO_ERROR;
2405 }
2406 
2407 /* Merge is more "aggressive" about resolving conflicts than traditional
2408  * patch or diff3.  Some people consider this behaviour to be a bug, see
2409  * http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=35014
2410  */
2411 static svn_error_t *
merge_adjacent_changes(apr_pool_t * pool)2412 merge_adjacent_changes(apr_pool_t *pool)
2413 {
2414   SVN_ERR(three_way_merge("adj1", "adj2", "adj3",
2415 
2416                           "foo\n"
2417                           "bar\n"
2418                           "baz\n",
2419 
2420                           "foo\n"
2421                           "new_bar\n"
2422                           "baz\n",
2423 
2424                           "zig\n"
2425                           "foo\n"
2426                           "bar\n"
2427                           "new_baz\n",
2428 
2429                           "zig\n"
2430                           "foo\n"
2431                           "new_bar\n"
2432                           "new_baz\n",
2433 
2434                           NULL,
2435                           svn_diff_conflict_display_modified_latest,
2436                           pool));
2437 
2438   return SVN_NO_ERROR;
2439 }
2440 
2441 /* Issue #4133, 'When sequences of whitespace characters at head of line
2442    strides chunk boundary, "diff -x -w" showing wrong change'.
2443    The magic number used in this test, 1<<17, is
2444    CHUNK_SIZE from ../../libsvn_diff/diff_file.c
2445  */
2446 static svn_error_t *
test_norm_offset(apr_pool_t * pool)2447 test_norm_offset(apr_pool_t *pool)
2448 {
2449   apr_size_t chunk_size = 1 << 17;
2450   const char *pattern1 = "       \n";
2451   const char *pattern2 = "\n\n\n\n\n\n\n\n";
2452   const char *pattern3 = "                        @@@@@@@\n";
2453   const char *pattern4 = "               \n";
2454   svn_stringbuf_t *original, *modified;
2455   svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
2456 
2457   /* The original contents become like this
2458 
2459      $ hexdump -C norm-offset-original
2460      00000000  20 20 20 20 20 20 20 0a  0a 0a 0a 0a 0a 0a 0a 0a  |       .........|
2461      00000010  0a 0a 0a 0a 0a 0a 0a 0a  0a 0a 0a 0a 0a 0a 0a 0a  |................|
2462      *
2463      0001fff0  0a 0a 0a 0a 0a 0a 0a 0a  20 20 20 20 20 20 20 20  |........        |
2464      00020000  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
2465      00020010  40 40 40 40 40 40 40 0a  0a 0a 0a 0a 0a 0a 0a 0a  |@@@@@@@.........|
2466      00020020  0a 0a 0a 0a 0a 0a 0a 0a  0a 0a 0a 0a 0a 0a 0a 0a  |................|
2467      *
2468      000203f0  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 0a  |               .|
2469      00020400
2470   */
2471   original = svn_stringbuf_create_ensure(chunk_size + 1024, pool);
2472   svn_stringbuf_appendcstr(original, pattern1);
2473   while (original->len < chunk_size - 8)
2474     {
2475       svn_stringbuf_appendcstr(original, pattern2);
2476     }
2477   svn_stringbuf_appendcstr(original, pattern3);
2478   while (original->len < chunk_size +1024 - 16)
2479     {
2480       svn_stringbuf_appendcstr(original, pattern2);
2481     }
2482   svn_stringbuf_appendcstr(original, pattern4);
2483 
2484   /* The modified contents become like this.
2485 
2486      $ hexdump -C norm-offset-modified
2487      00000000  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 0a  |               .|
2488      00000010  0a 0a 0a 0a 0a 0a 0a 0a  0a 0a 0a 0a 0a 0a 0a 0a  |................|
2489      *
2490      00020000  20 20 20 20 20 20 20 20  20 20 20 20 20 20 20 20  |                |
2491      00020010  20 20 20 20 20 20 20 20  40 40 40 40 40 40 40 0a  |        @@@@@@@.|
2492      00020020  0a 0a 0a 0a 0a 0a 0a 0a  0a 0a 0a 0a 0a 0a 0a 0a  |................|
2493      *
2494      000203f0  0a 0a 0a 0a 0a 0a 0a 0a  20 20 20 20 20 20 20 0a  |........       .|
2495      00020400
2496   */
2497   modified = svn_stringbuf_create_ensure(chunk_size + 1024, pool);
2498   svn_stringbuf_appendcstr(modified, pattern4);
2499   while (modified->len < chunk_size)
2500     {
2501       svn_stringbuf_appendcstr(modified, pattern2);
2502     }
2503   svn_stringbuf_appendcstr(modified, pattern3);
2504   while (modified->len < chunk_size +1024 - 8)
2505     {
2506       svn_stringbuf_appendcstr(modified, pattern2);
2507     }
2508   svn_stringbuf_appendcstr(modified, pattern1);
2509 
2510   /* Diff them.  Modulo whitespace, they are identical. */
2511   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
2512   SVN_ERR(two_way_diff("norm-offset-original", "norm-offset-modified",
2513                        original->data, modified->data, "",
2514                        diff_opts, pool));
2515 
2516   return SVN_NO_ERROR;
2517 }
2518 
2519 /* Issue #4283, 'When identical suffix started at a chunk boundary,
2520    incorrect diff was generated'.
2521    The magic number used in this test, (1<<17) and 50 are CHUNK_SIZE
2522    and SUFFIX_LINES_TO_KEEP from ../../libsvn_diff/diff_file.c, respectively.
2523  */
2524 #define ORIGINAL_CONTENTS_PATTERN "0123456789abcde\n"
2525 #define INSERTED_LINE "0123456789ABCDE\n"
2526 static svn_error_t *
test_identical_suffix(apr_pool_t * pool)2527 test_identical_suffix(apr_pool_t *pool)
2528 {
2529   apr_size_t lines_in_chunk = (1 << 17)
2530                               / (sizeof(ORIGINAL_CONTENTS_PATTERN) - 1);
2531   /* To let identical suffix start at a chunk boundary,
2532      insert a line at before (SUFFIX_LINES_TO_KEEP + 1) lines
2533      from tail of the previous chunk. */
2534   apr_size_t insert_pos = lines_in_chunk
2535 #ifdef SUFFIX_LINES_TO_KEEP
2536                           - SUFFIX_LINES_TO_KEEP
2537 #else
2538                           - 50
2539 #endif
2540                           - 1;
2541   apr_size_t i;
2542   svn_stringbuf_t *original, *modified;
2543 
2544   /* The original contents become like this.
2545 
2546      $ hexdump -C identical-suffix-original
2547      00000000  30 31 32 33 34 35 36 37  38 39 61 62 63 64 65 0a  |0123456789abcde.|
2548      *
2549      00020400
2550    */
2551   original = svn_stringbuf_create_ensure((1 << 17) + 1024, pool);
2552   for (i = 0; i < lines_in_chunk + 64; i++)
2553     {
2554       svn_stringbuf_appendbytes(original, ORIGINAL_CONTENTS_PATTERN,
2555                                 sizeof(ORIGINAL_CONTENTS_PATTERN) - 1);
2556     }
2557 
2558   /* The modified contents become like this.
2559 
2560      $ hexdump -C identical-suffix-modified
2561      00000000  30 31 32 33 34 35 36 37  38 39 61 62 63 64 65 0a  |0123456789abcde.|
2562      *
2563      00000400  30 31 32 33 34 35 36 37  38 39 41 42 43 44 45 0a  |0123456789ABCDE.|
2564      00000410  30 31 32 33 34 35 36 37  38 39 61 62 63 64 65 0a  |0123456789abcde.|
2565      *
2566      0001fcd0  30 31 32 33 34 35 36 37  38 39 41 42 43 44 45 0a  |0123456789ABCDE.|
2567      0001fce0  30 31 32 33 34 35 36 37  38 39 61 62 63 64 65 0a  |0123456789abcde.|
2568      *
2569      00020420
2570    */
2571   modified = svn_stringbuf_dup(original, pool);
2572   svn_stringbuf_insert(modified,
2573                        64 * (sizeof(ORIGINAL_CONTENTS_PATTERN) - 1),
2574                        INSERTED_LINE, sizeof(INSERTED_LINE) - 1);
2575   svn_stringbuf_insert(modified,
2576                        insert_pos * (sizeof(ORIGINAL_CONTENTS_PATTERN) - 1),
2577                        INSERTED_LINE, sizeof(INSERTED_LINE) - 1);
2578 
2579   SVN_ERR(two_way_diff("identical-suffix-original",
2580                        "identical-suffix-modified",
2581                        original->data, modified->data,
2582                        apr_psprintf(pool,
2583                                     "--- identical-suffix-original" NL
2584                                     "+++ identical-suffix-modified" NL
2585                                     "@@ -62,6 +62,7 @@" NL
2586                                     " " ORIGINAL_CONTENTS_PATTERN
2587                                     " " ORIGINAL_CONTENTS_PATTERN
2588                                     " " ORIGINAL_CONTENTS_PATTERN
2589                                     "+" INSERTED_LINE
2590                                     " " ORIGINAL_CONTENTS_PATTERN
2591                                     " " ORIGINAL_CONTENTS_PATTERN
2592                                     " " ORIGINAL_CONTENTS_PATTERN
2593                                     "@@ -%u,6 +%u,7 @@" NL
2594                                     " " ORIGINAL_CONTENTS_PATTERN
2595                                     " " ORIGINAL_CONTENTS_PATTERN
2596                                     " " ORIGINAL_CONTENTS_PATTERN
2597                                     "+" INSERTED_LINE
2598                                     " " ORIGINAL_CONTENTS_PATTERN
2599                                     " " ORIGINAL_CONTENTS_PATTERN
2600                                     " " ORIGINAL_CONTENTS_PATTERN,
2601                                     1 + (unsigned int)insert_pos - 3 - 1,
2602                                     1 + (unsigned int)insert_pos - 3),
2603                        NULL, pool));
2604 
2605   return SVN_NO_ERROR;
2606 }
2607 #undef ORIGINAL_CONTENTS_PATTERN
2608 #undef INSERTED_LINE
2609 
2610 /* The magic number used in this test, 1<<17, is
2611    CHUNK_SIZE from ../../libsvn_diff/diff_file.c
2612  */
2613 static svn_error_t *
test_token_compare(apr_pool_t * pool)2614 test_token_compare(apr_pool_t *pool)
2615 {
2616   apr_size_t chunk_size = 1 << 17;
2617   const char *pattern = "ABCDEFG\n";
2618   svn_stringbuf_t *original, *modified;
2619   svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
2620 
2621   diff_opts->ignore_space = svn_diff_file_ignore_space_all;
2622 
2623   original = svn_stringbuf_create_ensure(chunk_size * 2 + 8, pool);
2624   /* CHUNK_SIZE bytes */
2625   while (original->len < chunk_size - 8)
2626     {
2627       svn_stringbuf_appendcstr(original, pattern);
2628     }
2629   svn_stringbuf_appendcstr(original, "    @@@\n");
2630 
2631   modified = svn_stringbuf_create_ensure(chunk_size * 2 + 9, pool);
2632   /* CHUNK_SIZE+1 bytes, one ' ' more than original */
2633   while (modified->len < chunk_size - 8)
2634     {
2635       svn_stringbuf_appendcstr(modified, pattern);
2636     }
2637   svn_stringbuf_appendcstr(modified, "     @@@\n");
2638 
2639   /* regression test for reading exceeding the file size */
2640   SVN_ERR(two_way_diff("token-compare-original1", "token-compare-modified1",
2641                        original->data, modified->data, "",
2642                        diff_opts, pool));
2643 
2644   svn_stringbuf_appendcstr(original, "aaaaaaa\n");
2645   svn_stringbuf_appendcstr(modified, "bbbbbbb\n");
2646 
2647   /* regression test for comparison beyond the end-of-line */
2648   SVN_ERR(two_way_diff("token-compare-original2", "token-compare-modified2",
2649                        original->data, modified->data,
2650                        apr_psprintf(pool,
2651                                     "--- token-compare-original2" NL
2652                                     "+++ token-compare-modified2" NL
2653                                     "@@ -%u,4 +%u,4 @@"  NL
2654                                     " ABCDEFG\n"
2655                                     " ABCDEFG\n"
2656                                     "     @@@\n"
2657                                     "-aaaaaaa\n"
2658                                     "+bbbbbbb\n",
2659                                     (unsigned int)chunk_size/8 - 2,
2660                                     (unsigned int)chunk_size/8 - 2),
2661                        diff_opts, pool));
2662 
2663   /* CHUNK_SIZE*2 bytes */
2664   while (original->len <= chunk_size * 2 - 8)
2665     {
2666       svn_stringbuf_appendcstr(original, pattern);
2667     }
2668 
2669   /* CHUNK_SIZE*2+1 bytes, one ' ' more than original */
2670   while (modified->len <= chunk_size * 2 - 7)
2671     {
2672       svn_stringbuf_appendcstr(modified, pattern);
2673     }
2674 
2675   SVN_ERR(two_way_diff("token-compare-original2", "token-compare-modified2",
2676                        original->data, modified->data,
2677                        apr_psprintf(pool,
2678                                     "--- token-compare-original2" NL
2679                                     "+++ token-compare-modified2" NL
2680                                     "@@ -%u,7 +%u,7 @@"  NL
2681                                     " ABCDEFG\n"
2682                                     " ABCDEFG\n"
2683                                     "     @@@\n"
2684                                     "-aaaaaaa\n"
2685                                     "+bbbbbbb\n"
2686                                     " ABCDEFG\n"
2687                                     " ABCDEFG\n"
2688                                     " ABCDEFG\n",
2689                                     (unsigned int)chunk_size/8 - 2,
2690                                     (unsigned int)chunk_size/8 - 2),
2691                        diff_opts, pool));
2692 
2693   return SVN_NO_ERROR;
2694 }
2695 
2696 static svn_error_t *
two_way_issue_3362_v1(apr_pool_t * pool)2697 two_way_issue_3362_v1(apr_pool_t *pool)
2698 {
2699   svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
2700 
2701   SVN_ERR(two_way_diff("issue-3362-1-v1",
2702                        "issue-3362-2-v1",
2703                         /* File 1 */
2704                                 "line_1\n"
2705                                 "line_2\n"
2706                                 "line_3\n"
2707                                 "line_4\n"
2708                                 "line_5\n"
2709                                 "line_6\n"
2710                                 "line_7\n"
2711                                 "line_8\n"
2712                                 "line_9\n"
2713                                 "line_10\n"
2714                                 "line_11\n"
2715                                 "line_12\n"
2716                                 "line_13\n"
2717                                 "line_14\n"
2718                                 "line_15\n"
2719                                 "line_16\n"
2720                                 "line_17\n"
2721                                 "line_18\n"
2722                                 "line_19\n"
2723                                 "line_20\n"
2724                                 "line_21\n"
2725                                 "line_22\n"
2726                                 "line_23\n"
2727                                 "line_24\n"
2728                                 "line_25\n"
2729                                 "line_26\n"
2730                                 "line_27\n"
2731                                 "line_28\n"
2732                                 "line_29\n"
2733                                 "line_30\n",
2734                         /* File 2 */
2735                                 "line_1a\n"
2736                                 "line_2a\n"
2737                                 "line_3a\n"
2738                                 "line_1\n"
2739                                 "line_2\n"
2740                                 "line_3\n"
2741                                 "line_4\n"
2742                                 "line_5a\n"
2743                                 "line_6b\n"
2744                                 "line_7c\n"
2745                                 "line_8\n"
2746                                 "line_9\n"
2747                                 "line_10\n"
2748                                 "line_11a\n"
2749                                 "line_11b\n"
2750                                 "line_11c\n"
2751                                 "line_12\n"
2752                                 "line_13\n"
2753                                 "line_14\n"
2754                                 "line_15\n"
2755                                 "line_16\n"
2756                                 "line_17\n"
2757                                 "line_18\n"
2758                                 "line_19a\n"
2759                                 "line_19b\n"
2760                                 "line_19c\n"
2761                                 "line_20\n"
2762                                 "line_21\n"
2763                                 "line_22\n"
2764                                 "line_23\n"
2765                                 "line_24\n"
2766                                 "line_25\n"
2767                                 "line_26\n"
2768                                 "line_27\n"
2769                                 "line_27a\n",
2770                         /* Expected */
2771                         "--- issue-3362-1-v1" APR_EOL_STR
2772                         "+++ issue-3362-2-v1" APR_EOL_STR
2773                         "@@ -1,14 +1,19 @@" APR_EOL_STR
2774                         "+line_1a\n"
2775                         "+line_2a\n"
2776                         "+line_3a\n"
2777                         " line_1\n" /* 1.7 mem diff: line missing */
2778                         " line_2\n"
2779                         " line_3\n"
2780                         " line_4\n"
2781                         "-line_5\n"
2782                         "-line_6\n"
2783                         "-line_7\n"
2784                         "+line_5a\n"
2785                         "+line_6b\n"
2786                         "+line_7c\n"
2787                         " line_8\n"
2788                         " line_9\n"
2789                         " line_10\n"
2790                         "-line_11\n"
2791                         "+line_11a\n"
2792                         "+line_11b\n"
2793                         "+line_11c\n"
2794                         " line_12\n"
2795                         " line_13\n"
2796                         " line_14\n" /* 1.7 mem diff: line missing */
2797                         "@@ -16,7 +21,9 @@" APR_EOL_STR
2798                         " line_16\n"
2799                         " line_17\n"
2800                         " line_18\n"
2801                         "-line_19\n"
2802                         "+line_19a\n"
2803                         "+line_19b\n"
2804                         "+line_19c\n"
2805                         " line_20\n"
2806                         " line_21\n"
2807                         " line_22\n"
2808                         "@@ -25,6 +32,4 @@" APR_EOL_STR
2809                         " line_25\n"
2810                         " line_26\n"
2811                         " line_27\n"
2812                         "-line_28\n"
2813                         "-line_29\n"
2814                         "-line_30\n"
2815                         "+line_27a\n",
2816                         diff_opts, pool));
2817 
2818   return SVN_NO_ERROR;
2819 }
2820 
2821 static svn_error_t *
two_way_issue_3362_v2(apr_pool_t * pool)2822 two_way_issue_3362_v2(apr_pool_t *pool)
2823 {
2824   svn_diff_file_options_t *diff_opts = svn_diff_file_options_create(pool);
2825 
2826   SVN_ERR(two_way_diff("issue-3362-1-v2",
2827                        "issue-3362-2-v2",
2828                         /* File 1 */
2829                                 "line_1\n"
2830                                 "line_2\n"
2831                                 "line_3\n"
2832                                 "line_4\n"
2833                                 "line_5\n"
2834                                 "line_6\n"
2835                                 "line_7\n"
2836                                 "line_8\n"
2837                                 "line_9\n"
2838                                 "line_10\n"
2839                                 "line_11\n"
2840                                 "line_12\n"
2841                                 "line_13\n"
2842                                 "line_14\n"
2843                                 "line_15\n"
2844                                 "line_16\n"
2845                                 "line_17\n"
2846                                 "line_18\n"
2847                                 "line_19\n"
2848                                 "line_20\n"
2849                                 "line_21\n"
2850                                 "line_22\n"
2851                                 "line_23\n"
2852                                 "line_24\n"
2853                                 "line_25\n"
2854                                 "line_26\n"
2855                                 "line_27\n"
2856                                 "line_28\n"
2857                                 "line_29\n"
2858                                 "line_30\n",
2859                         /* File 2 */
2860                                 "line_1a\n"
2861                                 "line_1b\n"
2862                                 "line_1c\n"
2863                                 "line_1\n"
2864                                 "line_2\n"
2865                                 "line_3\n"
2866                                 "line_4\n"
2867                                 "line_5a\n"
2868                                 "line_5b\n"
2869                                 "line_5c\n"
2870                                 "line_6\n"
2871                                 "line_7\n"
2872                                 "line_8\n"
2873                                 "line_9\n"
2874                                 "line_10\n"
2875                                 "line_11a\n"
2876                                 "line_11b\n"
2877                                 "line_11c\n"
2878                                 "line_12\n"
2879                                 "line_13\n"
2880                                 "line_14\n"
2881                                 "line_15\n"
2882                                 "line_16\n"
2883                                 "line_17\n"
2884                                 "line_18\n"
2885                                 "line_19a\n"
2886                                 "line_19b\n"
2887                                 "line_19c\n"
2888                                 "line_20\n"
2889                                 "line_21\n"
2890                                 "line_22\n"
2891                                 "line_23\n"
2892                                 "line_24\n"
2893                                 "line_25\n"
2894                                 "line_26\n"
2895                                 "line_27a\n"
2896                                 "line_27b\n"
2897                                 "line_27c\n"
2898                                 "line_28\n"
2899                                 "line_29\n"
2900                                 "line_30\n",
2901                         /* Expected */
2902                         "--- issue-3362-1-v2" APR_EOL_STR
2903                         "+++ issue-3362-2-v2" APR_EOL_STR
2904                         "@@ -1,14 +1,21 @@" APR_EOL_STR
2905                         "+line_1a\n"
2906                         "+line_1b\n"
2907                         "+line_1c\n"
2908                         " line_1\n" /* 1.7 mem diff: line missing */
2909                         " line_2\n"
2910                         " line_3\n"
2911                         " line_4\n"
2912                         "-line_5\n"
2913                         "+line_5a\n"
2914                         "+line_5b\n"
2915                         "+line_5c\n"
2916                         " line_6\n"
2917                         " line_7\n"
2918                         " line_8\n"
2919                         " line_9\n"
2920                         " line_10\n"
2921                         "-line_11\n"
2922                         "+line_11a\n"
2923                         "+line_11b\n"
2924                         "+line_11c\n"
2925                         " line_12\n"
2926                         " line_13\n"
2927                         " line_14\n" /* 1.7 mem diff: line missing */
2928                         "@@ -16,7 +23,9 @@" APR_EOL_STR
2929                         " line_16\n"
2930                         " line_17\n"
2931                         " line_18\n"
2932                         "-line_19\n"
2933                         "+line_19a\n"
2934                         "+line_19b\n"
2935                         "+line_19c\n"
2936                         " line_20\n"
2937                         " line_21\n"
2938                         " line_22\n"
2939                         "@@ -24,7 +33,9 @@" APR_EOL_STR
2940                         " line_24\n"
2941                         " line_25\n"
2942                         " line_26\n"
2943                         "-line_27\n"
2944                         "+line_27a\n"
2945                         "+line_27b\n"
2946                         "+line_27c\n"
2947                         " line_28\n"
2948                         " line_29\n"
2949                         " line_30\n",
2950                         diff_opts, pool));
2951 
2952   return SVN_NO_ERROR;
2953 }
2954 
2955 static svn_error_t *
three_way_double_add(apr_pool_t * pool)2956 three_way_double_add(apr_pool_t *pool)
2957 {
2958   SVN_ERR(three_way_merge("doubleadd1", "doubleadd2", "doubleadd3",
2959                           "A\n"
2960                           "B\n"
2961                           "C\n"
2962                           "J\n"
2963                           "K\n"
2964                           "L",
2965 
2966                           "A\n"
2967                           "B\n"
2968                           "C\n"
2969                           "D\n" /* New line 1a */
2970                           "E\n" /* New line 2a */
2971                           "F\n" /* New line 3a*/
2972                           "J\n"
2973                           "K\n"
2974                           "L",
2975 
2976                           "A\n"
2977                           "B\n"
2978                           "O\n" /* Change C to O */
2979                           "P\n" /* New line 1b */
2980                           "Q\n" /* New line 2b */
2981                           "R\n" /* New line 3b */
2982                           "J\n"
2983                           "K\n"
2984                           "L",
2985 
2986                           /* With s/C/O/ we expect something like this,
2987                              but the current (1.9/trunk) result is a
2988                              succeeded merge to a combined result.
2989 
2990                              ### I'm guessing this result needs tweaks before it
2991                                  will be a PASS. */
2992                           "A\n"
2993                           "B\n"
2994                           "<<<<<<< doubleadd2\n"
2995                           "C\n"
2996                           "D\n" /* New line 1a */
2997                           "E\n" /* New line 2a */
2998                           "F\n" /* New line 3a*/
2999                           "=======\n"
3000                           "O\n"
3001                           "P\n" /* New line 1b */
3002                           "Q\n" /* New line 2b */
3003                           "R\n" /* New line 3b */
3004                           ">>>>>>> doubleadd3\n"
3005                           "J\n"
3006                           "K\n"
3007                           "L",
3008                           NULL,
3009                           svn_diff_conflict_display_modified_original_latest,
3010                           pool));
3011 
3012   SVN_ERR(three_way_merge("doubleadd1", "doubleadd2", "doubleadd3",
3013                           "A\n"
3014                           "B\n"
3015                           "C\n"
3016                           "J\n"
3017                           "K\n"
3018                           "L",
3019 
3020                           "A\n"
3021                           "B\n"
3022                           "C\n"
3023                           "D\n" /* New line 1a */
3024                           "E\n" /* New line 2a */
3025                           "F\n" /* New line 3a*/
3026                           "K\n"
3027                           "L",
3028 
3029                           "A\n"
3030                           "B\n"
3031                           "O\n" /* Change C to O */
3032                           "P\n" /* New line 1b */
3033                           "Q\n" /* New line 2b */
3034                           "R\n" /* New line 3b */
3035                           "J\n"
3036                           "K\n"
3037                           "L",
3038 
3039                           /* With s/C/O/ we expect something like this,
3040                           but the current (1.9/trunk) result is a
3041                           succeeded merge to a combined result.
3042 
3043                           ### I'm guessing this result needs tweaks before it
3044                           will be a PASS. */
3045                           "A\n"
3046                           "B\n"
3047                           "<<<<<<< doubleadd2\n"
3048                           "C\n"
3049                           "D\n" /* New line 1a */
3050                           "E\n" /* New line 2a */
3051                           "F\n" /* New line 3a*/
3052                           "=======\n"
3053                           "O\n"
3054                           "P\n" /* New line 1b */
3055                           "Q\n" /* New line 2b */
3056                           "R\n" /* New line 3b */
3057                           "J\n"
3058                           ">>>>>>> doubleadd3\n"
3059                           "K\n"
3060                           "L",
3061                           NULL,
3062                           svn_diff_conflict_display_modified_original_latest,
3063                           pool));
3064 
3065   return SVN_NO_ERROR;
3066 }
3067 
3068 /* ========================================================================== */
3069 
3070 
3071 static int max_threads = 4;
3072 
3073 static struct svn_test_descriptor_t test_funcs[] =
3074   {
3075     SVN_TEST_NULL,
3076     SVN_TEST_PASS2(dump_core,
3077                    "these dump core"),
3078     SVN_TEST_PASS2(test_two_way_unified,
3079                    "2-way unified diff and trivial merge"),
3080     SVN_TEST_PASS2(test_two_way_unified_suspect,
3081                    "2-way unified diff where output is suspect"),
3082     SVN_TEST_PASS2(test_three_way_merge_no_overlap,
3083                    "3-way merge, non-overlapping changes"),
3084     SVN_TEST_PASS2(test_three_way_merge_with_overlap,
3085                    "3-way merge, non-conflicting overlapping changes"),
3086     SVN_TEST_PASS2(test_three_way_merge_with_conflict,
3087                    "3-way merge, conflicting overlapping changes"),
3088     SVN_TEST_PASS2(random_trivial_merge,
3089                    "random trivial merge"),
3090     SVN_TEST_PASS2(random_three_way_merge,
3091                    "random 3-way merge"),
3092     SVN_TEST_PASS2(merge_with_part_already_present,
3093                    "merge with part already present"),
3094     SVN_TEST_PASS2(merge_adjacent_changes,
3095                    "3-way merge, adjacent changes"),
3096     SVN_TEST_PASS2(test_three_way_merge_conflict_styles,
3097                    "3-way merge with conflict styles"),
3098     SVN_TEST_PASS2(test_diff4,
3099                    "4-way merge; see variance-adjusted-patching.html"),
3100     SVN_TEST_PASS2(test_norm_offset,
3101                    "offset of the normalized token"),
3102     SVN_TEST_PASS2(test_identical_suffix,
3103                    "identical suffix starts at the boundary of a chunk"),
3104     SVN_TEST_PASS2(test_token_compare,
3105                    "compare tokens at the chunk boundary"),
3106     SVN_TEST_PASS2(two_way_issue_3362_v1,
3107                    "2-way issue #3362 test v1"),
3108     SVN_TEST_PASS2(two_way_issue_3362_v2,
3109                    "2-way issue #3362 test v2"),
3110     SVN_TEST_XFAIL2(three_way_double_add,
3111                    "3-way merge, double add"),
3112     SVN_TEST_NULL
3113   };
3114 
3115 SVN_TEST_MAIN
3116