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