2 * mergeinfo-test.c -- test the mergeinfo functions
4 * ====================================================================
5 * Copyright (c) 2006-2007 CollabNet. All rights reserved.
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution. The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
13 * This software consists of voluntary contributions made by many
14 * individuals. For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
22 #include <apr_tables.h>
24 #include "svn_pools.h"
25 #include "svn_types.h"
26 #include "svn_mergeinfo.h"
27 #include "private/svn_mergeinfo_private.h"
28 #include "../svn_test.h"
30 /* A quick way to create error messages. */
32 fail(apr_pool_t
*pool
, const char *fmt
, ...)
38 msg
= apr_pvsprintf(pool
, fmt
, ap
);
41 return svn_error_create(SVN_ERR_TEST_FAILED
, 0, msg
);
44 #define MAX_NBR_RANGES 3
46 /* Verify that INPUT is parsed properly, and returns an error if
47 parsing fails, or incorret parsing is detected. Assumes that INPUT
48 contains only one path -> ranges mapping, and that EXPECTED_RANGES points
49 to the first range in an array whose size is greater than or equal to
50 the number of ranges in INPUTS path -> ranges mapping but less than
51 MAX_NBR_RANGES. If fewer than MAX_NBR_RANGES ranges are present, then the
52 trailing expected_ranges should be have their end revision set to 0. */
54 verify_mergeinfo_parse(const char *input
,
55 const char *expected_path
,
56 const svn_merge_range_t
*expected_ranges
,
60 apr_hash_t
*path_to_merge_ranges
;
63 /* Test valid input. */
64 err
= svn_mergeinfo_parse(&path_to_merge_ranges
, input
, pool
);
65 if (err
|| apr_hash_count(path_to_merge_ranges
) != 1)
66 return svn_error_createf(SVN_ERR_TEST_FAILED
, err
,
67 "svn_mergeinfo_parse (%s) failed unexpectedly",
69 for (hi
= apr_hash_first(pool
, path_to_merge_ranges
); hi
;
70 hi
= apr_hash_next(hi
))
74 apr_array_header_t
*ranges
;
75 svn_merge_range_t
*range
;
78 apr_hash_this(hi
, &path
, NULL
, &val
);
80 if (strcmp((const char *) path
, expected_path
) != 0)
81 return fail(pool
, "svn_mergeinfo_parse (%s) failed to parse the "
82 "correct path (%s)", input
, expected_path
);
84 /* Test each parsed range. */
85 for (j
= 0; j
< ranges
->nelts
; j
++)
87 range
= APR_ARRAY_IDX(ranges
, j
, svn_merge_range_t
*);
88 if (range
->start
!= expected_ranges
[j
].start
89 || range
->end
!= expected_ranges
[j
].end
90 || range
->inheritable
!= expected_ranges
[j
].inheritable
)
91 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
92 "svn_mergeinfo_parse (%s) failed to "
93 "parse the correct range",
97 /* Were we expecting any more ranges? */
98 if (j
< MAX_NBR_RANGES
- 1
99 && !expected_ranges
[j
].end
== 0)
100 return svn_error_createf(SVN_ERR_TEST_FAILED
, NULL
,
101 "svn_mergeinfo_parse (%s) failed to "
102 "produce the expected number of ranges",
109 /* Some of our own global variables (for simplicity), which map paths
111 static apr_hash_t
*info1
, *info2
;
113 #define NBR_MERGEINFO_VALS 5
114 /* Valid mergeinfo values. */
115 static const char * const mergeinfo_vals
[NBR_MERGEINFO_VALS
] =
119 "/trunk: 5,7-9,10,11,13,14",
120 "/trunk: 3-10,11*,13,14",
121 "/branch: 1,2-18*,33*"
123 /* Paths corresponding to mergeinfo_vals. */
124 static const char * const mergeinfo_paths
[NBR_MERGEINFO_VALS
] =
132 /* First ranges from the paths identified by mergeinfo_paths. */
133 static svn_merge_range_t mergeinfo_ranges
[NBR_MERGEINFO_VALS
][MAX_NBR_RANGES
] =
137 { {4, 5, TRUE
}, { 6, 11, TRUE
}, {12, 14, TRUE
} },
138 { {2, 10, TRUE
}, {10, 11, FALSE
}, {12, 14, TRUE
} },
139 { {0, 1, TRUE
}, { 1, 18, FALSE
}, {32, 33, FALSE
} }
143 test_parse_single_line_mergeinfo(const char **msg
,
144 svn_boolean_t msg_only
,
145 svn_test_opts_t
*opts
,
150 *msg
= "parse single line mergeinfo";
155 for (i
= 0; i
< NBR_MERGEINFO_VALS
; i
++)
156 SVN_ERR(verify_mergeinfo_parse(mergeinfo_vals
[i
], mergeinfo_paths
[i
],
157 mergeinfo_ranges
[i
], pool
));
162 static const char *single_mergeinfo
= "/trunk: 5,7-9,10,11,13,14";
165 test_mergeinfo_dup(const char **msg
,
166 svn_boolean_t msg_only
,
167 svn_test_opts_t
*opts
,
170 apr_hash_t
*orig_mergeinfo
, *copied_mergeinfo
;
172 apr_array_header_t
*rangelist
;
174 *msg
= "copy a mergeinfo data structure";
179 /* Assure that copies which should be empty turn out that way. */
180 subpool
= svn_pool_create(pool
);
181 orig_mergeinfo
= apr_hash_make(subpool
);
182 copied_mergeinfo
= svn_mergeinfo_dup(orig_mergeinfo
, subpool
);
183 if (apr_hash_count(copied_mergeinfo
) != 0)
184 return fail(pool
, "Copied mergeinfo should be empty");
186 /* Create some mergeinfo, copy it using another pool, then destroy
187 the pool with which the original mergeinfo was created. */
188 SVN_ERR(svn_mergeinfo_parse(&orig_mergeinfo
, single_mergeinfo
, subpool
));
189 copied_mergeinfo
= svn_mergeinfo_dup(orig_mergeinfo
, pool
);
190 svn_pool_destroy(subpool
);
191 if (apr_hash_count(copied_mergeinfo
) != 1)
192 return fail(pool
, "Copied mergeinfo should contain one merge source");
193 rangelist
= apr_hash_get(copied_mergeinfo
, "/trunk", APR_HASH_KEY_STRING
);
195 return fail(pool
, "Expected copied mergeinfo; got nothing");
196 if (rangelist
->nelts
!= 3)
197 return fail(pool
, "Copied mergeinfo should contain 3 revision ranges, "
198 "rather than the %d it contains", rangelist
->nelts
);
204 test_parse_combine_rangeinfo(const char **msg
,
205 svn_boolean_t msg_only
,
206 svn_test_opts_t
*opts
,
209 apr_array_header_t
*result
;
210 svn_merge_range_t
*resultrange
;
212 *msg
= "parse single line mergeinfo and combine ranges";
217 SVN_ERR(svn_mergeinfo_parse(&info1
, single_mergeinfo
, pool
));
219 if (apr_hash_count(info1
) != 1)
220 return fail(pool
, "Wrong number of paths in parsed mergeinfo");
222 result
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
224 return fail(pool
, "Missing path in parsed mergeinfo");
226 /* /trunk should have three ranges, 5-5, 7-11, 13-14 */
227 if (result
->nelts
!= 3)
228 return fail(pool
, "Parsing failed to combine ranges");
230 resultrange
= APR_ARRAY_IDX(result
, 0, svn_merge_range_t
*);
232 if (resultrange
->start
!= 4 || resultrange
->end
!= 5)
233 return fail(pool
, "Range combining produced wrong result");
235 resultrange
= APR_ARRAY_IDX(result
, 1, svn_merge_range_t
*);
237 if (resultrange
->start
!= 6 || resultrange
->end
!= 11)
238 return fail(pool
, "Range combining produced wrong result");
240 resultrange
= APR_ARRAY_IDX(result
, 2, svn_merge_range_t
*);
242 if (resultrange
->start
!= 12 || resultrange
->end
!= 14)
243 return fail(pool
, "Range combining produced wrong result");
249 #define NBR_BROKEN_MERGEINFO_VALS 34
250 /* Invalid mergeinfo values. */
251 static const char * const broken_mergeinfo_vals
[NBR_BROKEN_MERGEINFO_VALS
] =
253 /* Invalid grammar */
255 "/trunk: 5,7-9,10,11,13,14,",
256 "/trunk 5,7-9,10,11,13,14",
257 "/trunk:5 7--9 10 11 13 14",
259 "/trunk:3-6,15,18,9,22",
261 "/trunk:3-6*,15*,18*,9,22*",
263 /* Overlapping revs differing inheritability */
272 /* Overlapping revs same inheritability */
281 /* Reversed revision ranges */
284 "/trunk:3,7-12,22-20,25",
285 "/trunk:3,7,22-20*,25-30",
286 /* Range with same start and end revision */
289 "/trunk:3,7-12,20-20,25",
290 "/trunk:3,7,20-20*,25-30",
291 /* path mapped to range with no revisions */
293 "/trunk:2-9\n/branch:"
297 test_parse_broken_mergeinfo(const char **msg
,
298 svn_boolean_t msg_only
,
299 svn_test_opts_t
*opts
,
304 *msg
= "parse broken single line mergeinfo";
309 /* Trigger some error(s) with mal-formed input. */
310 for (i
= 0; i
< NBR_BROKEN_MERGEINFO_VALS
; i
++)
312 err
= svn_mergeinfo_parse(&info1
, broken_mergeinfo_vals
[i
], pool
);
313 if (err
== SVN_NO_ERROR
)
314 return fail(pool
, "svn_mergeinfo_parse (%s) failed to detect an error",
315 broken_mergeinfo_vals
[i
]);
317 svn_error_clear(err
);
324 static const char *mergeinfo1
= "/trunk: 3,5,7-9,10,11,13,14\n/fred:8-10";
326 #define NBR_RANGELIST_DELTAS 4
328 /* Verify that ACTUAL_RANGELIST matches EXPECTED_RANGES (an array of
329 NBR_EXPECTED length). Return an error based careful examination if
330 they do not match. FUNC_VERIFIED is the name of the API being
331 verified (e.g. "svn_rangelist_intersect"), while TYPE is a word
332 describing what the ranges being examined represent. */
334 verify_ranges_match(apr_array_header_t
*actual_rangelist
,
335 svn_merge_range_t
*expected_ranges
, int nbr_expected
,
336 const char *func_verified
, const char *type
,
341 if (actual_rangelist
->nelts
!= nbr_expected
)
342 return fail(pool
, "%s should report %d range %ss, but found %d",
343 func_verified
, nbr_expected
, type
, actual_rangelist
->nelts
);
345 for (i
= 0; i
< actual_rangelist
->nelts
; i
++)
347 svn_merge_range_t
*range
= APR_ARRAY_IDX(actual_rangelist
, i
,
348 svn_merge_range_t
*);
349 if (range
->start
!= expected_ranges
[i
].start
350 || range
->end
!= expected_ranges
[i
].end
351 || range
->inheritable
!= expected_ranges
[i
].inheritable
)
352 return fail(pool
, "%s should report range %ld-%ld%s, "
353 "but found %ld-%ld%s",
354 func_verified
, expected_ranges
[i
].start
,
355 expected_ranges
[i
].end
,
356 expected_ranges
[i
].inheritable
? "*" : "",
357 range
->start
, range
->end
,
358 range
->inheritable
? "*" : "");
363 /* Verify that DELTAS matches EXPECTED_DELTAS (both expected to
364 contain only a rangelist for "/trunk"). Return an error based
365 careful examination if they do not match. FUNC_VERIFIED is the
366 name of the API being verified (e.g. "svn_mergeinfo_diff"), while
367 TYPE is a word describing what the deltas being examined
370 verify_mergeinfo_deltas(apr_hash_t
*deltas
, svn_merge_range_t
*expected_deltas
,
371 const char *func_verified
, const char *type
,
374 apr_array_header_t
*rangelist
;
376 if (apr_hash_count(deltas
) != 1)
377 /* Deltas on "/trunk" expected. */
378 return fail(pool
, "%s should report 1 path %s, but found %d",
379 func_verified
, type
, apr_hash_count(deltas
));
381 rangelist
= apr_hash_get(deltas
, "/trunk", APR_HASH_KEY_STRING
);
382 if (rangelist
== NULL
)
383 return fail(pool
, "%s failed to produce a rangelist for /trunk",
386 return verify_ranges_match(rangelist
, expected_deltas
, NBR_RANGELIST_DELTAS
,
387 func_verified
, type
, pool
);
391 test_diff_mergeinfo(const char **msg
,
392 svn_boolean_t msg_only
,
393 svn_test_opts_t
*opts
,
396 apr_hash_t
*deleted
, *added
, *from
, *to
;
397 svn_merge_range_t expected_rangelist_deletions
[NBR_RANGELIST_DELTAS
] =
398 { {6, 7, TRUE
}, {8, 9, TRUE
}, {10, 11, TRUE
}, {32, 34, TRUE
} };
399 svn_merge_range_t expected_rangelist_additions
[NBR_RANGELIST_DELTAS
] =
400 { {1, 2, TRUE
}, {4, 6, TRUE
}, {12, 16, TRUE
}, {29, 30, TRUE
} };
402 *msg
= "diff of mergeinfo";
406 SVN_ERR(svn_mergeinfo_parse(&from
, "/trunk: 1,3-4,7,9,11-12,31-34", pool
));
407 SVN_ERR(svn_mergeinfo_parse(&to
, "/trunk: 1-6,12-16,30-32", pool
));
408 /* On /trunk: deleted (7, 9, 11, 33-34) and added (2, 5-6, 13-16, 30) */
409 SVN_ERR(svn_mergeinfo_diff(&deleted
, &added
, from
, to
,
412 /* Verify calculation of range list deltas. */
413 SVN_ERR(verify_mergeinfo_deltas(deleted
, expected_rangelist_deletions
,
414 "svn_mergeinfo_diff", "deletion", pool
));
415 SVN_ERR(verify_mergeinfo_deltas(added
, expected_rangelist_additions
,
416 "svn_mergeinfo_diff", "addition", pool
));
422 test_rangelist_reverse(const char **msg
,
423 svn_boolean_t msg_only
,
424 svn_test_opts_t
*opts
,
427 apr_array_header_t
*rangelist
;
428 svn_merge_range_t expected_rangelist
[3] =
429 { {10, 9, TRUE
}, {7, 4, TRUE
}, {3, 2, TRUE
} };
431 *msg
= "reversal of rangelist";
435 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 3,5-7,10", pool
));
436 rangelist
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
438 SVN_ERR(svn_rangelist_reverse(rangelist
, pool
));
440 return verify_ranges_match(rangelist
, expected_rangelist
, 3,
441 "svn_rangelist_reverse", "reversal", pool
);
445 test_rangelist_count_revs(const char **msg
,
446 svn_boolean_t msg_only
,
447 svn_test_opts_t
*opts
,
450 apr_array_header_t
*rangelist
;
451 apr_uint64_t nbr_revs
;
453 *msg
= "counting revs in rangelist";
457 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 3,5-7,10", pool
));
458 rangelist
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
460 nbr_revs
= svn_rangelist_count_revs(rangelist
);
463 return fail(pool
, "expecting 5 revs in count, found %d", nbr_revs
);
469 test_rangelist_to_revs(const char **msg
,
470 svn_boolean_t msg_only
,
471 svn_test_opts_t
*opts
,
474 apr_array_header_t
*revs
, *rangelist
;
475 svn_revnum_t expected_revs
[] = {3, 5, 6, 7, 10};
478 *msg
= "returning revs in rangelist";
482 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 3,5-7,10", pool
));
483 rangelist
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
485 SVN_ERR(svn_rangelist_to_revs(&revs
, rangelist
, pool
));
487 for (i
= 0; i
< revs
->nelts
; i
++)
489 svn_revnum_t rev
= APR_ARRAY_IDX(revs
, i
, svn_revnum_t
);
491 if (rev
!= expected_revs
[i
])
492 return fail(pool
, "rev mis-match at position %d: expecting %d, "
493 "found %d", i
, expected_revs
[i
], rev
);
500 test_rangelist_intersect(const char **msg
,
501 svn_boolean_t msg_only
,
502 svn_test_opts_t
*opts
,
505 apr_array_header_t
*rangelist1
, *rangelist2
, *intersection
;
506 svn_merge_range_t expected_intersection
[4] =
507 { {0, 1, TRUE
}, {2, 4, TRUE
}, {11, 12, TRUE
}, {30, 32, TRUE
} };
509 *msg
= "intersection of rangelists";
513 SVN_ERR(svn_mergeinfo_parse(&info1
, "/trunk: 1-6,12-16,30-32", pool
));
514 SVN_ERR(svn_mergeinfo_parse(&info2
, "/trunk: 1,3-4,7,9,11-12,31-34", pool
));
515 rangelist1
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
516 rangelist2
= apr_hash_get(info2
, "/trunk", APR_HASH_KEY_STRING
);
518 SVN_ERR(svn_rangelist_intersect(&intersection
, rangelist1
, rangelist2
,
521 return verify_ranges_match(intersection
, expected_intersection
, 4,
522 "svn_rangelist_intersect", "intersect", pool
);
526 test_merge_mergeinfo(const char **msg
,
527 svn_boolean_t msg_only
,
528 svn_test_opts_t
*opts
,
532 svn_stringbuf_t
*output
;
534 /* Structures and constants for test_merge_mergeinfo() */
535 /* Number of svn_mergeinfo_merge test sets */
536 #define NBR_MERGEINFO_MERGES 12
538 /* Maximum number of expected paths in the results
539 of the svn_mergeinfo_merge tests */
540 #define MAX_NBR_MERGEINFO_PATHS 4
542 /* Maximum number of expected ranges in the results
543 of the svn_mergeinfo_merge tests */
544 #define MAX_NBR_MERGEINFO_RANGES 10
546 /* Struct to store a path and it's expected ranges,
547 i.e. the expected result of an svn_mergeinfo_merge
549 struct mergeinfo_merge_path_range
552 svn_merge_range_t expected_rngs
[MAX_NBR_MERGEINFO_RANGES
];
555 /* Struct for svn_mergeinfo_merge test data.
556 If MERGEINFO1 and MERGEINFO2 are parsed to a hash with
557 svn_mergeinfo_parse() and then merged with svn_mergeinfo_merge(),
558 the resulting hash should have EXPECTED_PATHS number of paths
559 mapped to rangelists and each mapping is described by PATH_RNGS
560 where PATH_RNGS->PATH is not NULL. */
561 struct mergeinfo_merge_test_data
563 const char *mergeinfo1
;
564 const char *mergeinfo2
;
566 struct mergeinfo_merge_path_range path_rngs
[MAX_NBR_MERGEINFO_PATHS
];
569 static struct mergeinfo_merge_test_data mergeinfo
[NBR_MERGEINFO_MERGES
] =
571 /* One path, intersecting inheritable ranges */
574 { {"/trunk", { {4, 10, TRUE
} } } } },
576 /* One path, intersecting non-inheritable ranges */
579 { {"/trunk", { {4, 10, FALSE
} } } } },
581 /* One path, intersecting ranges with different inheritability */
584 { {"/trunk", { {4, 10, TRUE
} } } } },
586 /* One path, intersecting ranges with different inheritability */
589 { {"/trunk", { {4, 5, FALSE
}, {5, 6, TRUE
}, {6, 10, FALSE
} } } } },
591 /* Adjacent ranges all inheritable ranges */
592 { "/trunk: 1,3,5-11,13",
593 "/trunk: 2,4,12,14-22", 1,
594 { {"/trunk", { {0, 22, TRUE
} } } } },
596 /* Adjacent ranges all non-inheritable ranges */
597 { "/trunk: 1*,3*,5-11*,13*",
598 "/trunk: 2*,4*,12*,14-22*", 1,
599 { {"/trunk", { {0, 22, FALSE
} } } } },
601 /* Adjacent ranges differing inheritability */
602 { "/trunk: 1*,3*,5-11*,13*",
603 "/trunk: 2,4,12,14-22", 1,
604 { {"/trunk", { { 0, 1, FALSE
}, { 1, 2, TRUE
},
605 { 2, 3, FALSE
}, { 3, 4, TRUE
},
606 { 4, 11, FALSE
}, {11, 12, TRUE
},
607 {12, 13, FALSE
}, {13, 22, TRUE
} } } } },
609 /* Adjacent ranges differing inheritability */
610 { "/trunk: 1,3,5-11,13",
611 "/trunk: 2*,4*,12*,14-22*", 1,
612 { {"/trunk", { { 0, 1, TRUE
}, { 1, 2, FALSE
},
613 { 2, 3, TRUE
}, { 3, 4, FALSE
},
614 { 4, 11, TRUE
}, {11, 12, FALSE
},
615 {12, 13, TRUE
}, {13, 22, FALSE
} } } } },
617 /* Two paths all inheritable ranges */
618 { "/trunk: 3,5,7-9,10,11,13,14\n/fred:8-10",
619 "/trunk: 1-4,6\n/fred:9-12", 2,
620 { {"/trunk", { {0, 11, TRUE
}, {12, 14, TRUE
} } },
621 {"/fred", { {7, 12, TRUE
} } } } },
623 /* Two paths all non-inheritable ranges */
624 { "/trunk: 3*,5*,7-9*,10*,11*,13*,14*\n/fred:8-10*",
625 "/trunk: 1-4*,6*\n/fred:9-12*", 2,
626 { {"/trunk", { {0, 11, FALSE
}, {12, 14, FALSE
} } },
627 {"/fred", { {7, 12, FALSE
} } } } },
629 /* Two paths mixed inheritability */
630 { "/trunk: 3,5*,7-9,10,11*,13,14\n/fred:8-10",
631 "/trunk: 1-4,6\n/fred:9-12*", 2,
632 { {"/trunk", { { 0, 4, TRUE
}, { 4, 5, FALSE
}, {5, 10, TRUE
},
633 {10, 11, FALSE
}, {12, 14, TRUE
} } },
634 {"/fred", { { 7, 10, TRUE
}, {10, 12, FALSE
} } } } },
636 /* A slew of different paths but no ranges to be merged */
637 { "/trunk: 3,5-9*\n/betty: 2-4",
638 "/fred: 1-18\n/barney: 1,3-43", 4,
639 { {"/trunk", { {2, 3, TRUE
}, {4, 9, FALSE
} } },
640 {"/betty", { {1, 4, TRUE
} } },
641 {"/barney", { {0, 1, TRUE
}, {2, 43, TRUE
} } },
642 {"/fred", { {0, 18, TRUE
} } } } }
645 *msg
= "merging of mergeinfo hashs";
649 for (i
= 0; i
< NBR_MERGEINFO_MERGES
; i
++)
652 SVN_ERR(svn_mergeinfo_parse(&info1
, mergeinfo
[i
].mergeinfo1
, pool
));
653 SVN_ERR(svn_mergeinfo_parse(&info2
, mergeinfo
[i
].mergeinfo2
, pool
));
654 SVN_ERR(svn_mergeinfo_merge(info1
, info2
, pool
));
655 SVN_ERR(svn_mergeinfo_to_stringbuf(&output
, info1
, pool
));
656 if (mergeinfo
[i
].expected_paths
!= apr_hash_count(info1
))
657 return fail(pool
, "Wrong number of paths in merged mergeinfo");
658 for (j
= 0; j
< mergeinfo
[i
].expected_paths
; j
++)
661 apr_array_header_t
*rangelist
=
662 apr_hash_get(info1
, mergeinfo
[i
].path_rngs
[j
].path
,
663 APR_HASH_KEY_STRING
);
665 return fail(pool
, "Missing path '%s' in merged mergeinfo",
666 mergeinfo
[i
].path_rngs
->path
);
667 for (k
= 0; k
< rangelist
->nelts
; k
++)
669 svn_merge_range_t
*ranges
=
670 APR_ARRAY_IDX(rangelist
, k
, svn_merge_range_t
*);
672 != mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].start
674 != mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].end
675 || ranges
->inheritable
676 != mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].inheritable
)
679 "Range'%i-%i%s' not found in merged mergeinfo",
680 mergeinfo
[i
].path_rngs
->expected_rngs
[k
].start
,
681 mergeinfo
[i
].path_rngs
->expected_rngs
[k
].end
,
682 mergeinfo
[i
].path_rngs
->expected_rngs
[k
].inheritable
685 /* Were more ranges expected? */
686 if (k
< MAX_NBR_MERGEINFO_RANGES
687 && mergeinfo
[i
].path_rngs
[j
].expected_rngs
[k
].start
!= 0)
689 "Not all expected ranges found in merged mergeinfo");
697 test_remove_rangelist(const char **msg
,
698 svn_boolean_t msg_only
,
699 svn_test_opts_t
*opts
,
703 svn_error_t
*err
, *child_err
;
704 apr_array_header_t
*output
, *eraser
, *whiteboard
;
706 /* Struct for svn_rangelist_remove test data.
707 Parse WHITEBOARD and ERASER to hashes and then get the rangelist for
710 Remove ERASER's rangelist from WHITEBOARD's twice, once while
711 considering inheritance and once while not. In the first case the
712 resulting rangelist should have EXPECTED_RANGES_CONSIDER_INHERITANCE
713 number of ranges and these ranges should match the ranges in
714 EXPECTED_REMOVED_CONSIDER_INHERITANCE. In the second case there
715 should be EXPECTED_RANGES_IGNORE_INHERITANCE number of ranges and
716 these should match EXPECTED_REMOVED_IGNORE_INHERITANCE */
717 struct rangelist_remove_test_data
719 const char *whiteboard
;
721 int expected_ranges_consider_inheritance
;
722 svn_merge_range_t expected_removed_consider_inheritance
[10];
723 int expected_ranges_ignore_inheritance
;
724 svn_merge_range_t expected_removed_ignore_inheritance
[10];
727 #define SIZE_OF_RANGE_REMOVE_TEST_ARRAY 15
729 /* The actual test data */
730 struct rangelist_remove_test_data test_data
[SIZE_OF_RANGE_REMOVE_TEST_ARRAY
] =
732 /* Eraser is a proper subset of whiteboard */
733 {"/A: 1-44", "/A: 5", 2, { {0, 4, TRUE
}, {5, 44, TRUE
}},
734 2, { {0, 4, TRUE
}, {5, 44, TRUE
}}},
735 {"/A: 1-44*", "/A: 5", 1, { {0, 44, FALSE
} },
736 2, { {0, 4, FALSE
}, {5, 44, FALSE
}}},
737 {"/A: 1-44", "/A: 5*", 1, { {0, 44, TRUE
} },
738 2, { {0, 4, TRUE
}, {5, 44, TRUE
}}},
739 {"/A: 1-44*", "/A: 5*", 2, { {0, 4, FALSE
}, {5, 44, FALSE
}},
740 2, { {0, 4, FALSE
}, {5, 44, FALSE
}}},
741 /* Non-intersecting ranges...nothing is removed */
742 {"/A: 2-9,14-19", "/A: 12", 2, { {1, 9, TRUE
}, {13, 19, TRUE
}},
743 2, { {1, 9, TRUE
}, {13, 19, TRUE
}}},
744 {"/A: 2-9*,14-19*", "/A: 12", 2, { {1, 9, FALSE
}, {13, 19, FALSE
}},
745 2, { {1, 9, FALSE
}, {13, 19, FALSE
}}},
746 {"/A: 2-9,14-19", "/A: 12*", 2, { {1, 9, TRUE
}, {13, 19, TRUE
}},
747 2, { {1, 9, TRUE
}, {13, 19, TRUE
}}},
748 {"/A: 2-9*,14-19*", "/A: 12*", 2, { {1, 9, FALSE
}, {13, 19, FALSE
}},
749 2, { {1, 9, FALSE
}, {13, 19, FALSE
}}},
750 /* Eraser overlaps whiteboard */
751 {"/A: 1,9-17", "/A: 12-20", 2, { {0, 1, TRUE
}, {8, 11, TRUE
}},
752 2, { {0, 1, TRUE
}, {8, 11, TRUE
}}},
753 {"/A: 1,9-17*", "/A: 12-20", 2, { {0, 1, TRUE
}, {8, 17, FALSE
}},
754 2, { {0, 1, TRUE
}, {8, 11, FALSE
}}},
755 {"/A: 1,9-17", "/A: 12-20*", 2, { {0, 1, TRUE
}, {8, 17, TRUE
}},
756 2, { {0, 1, TRUE
}, {8, 11, TRUE
}}},
757 {"/A: 1,9-17*", "/A: 12-20*", 2, { {0, 1, TRUE
}, {8, 11, FALSE
}},
758 2, { {0, 1, TRUE
}, {8, 11, FALSE
}}},
759 /* Empty mergeinfo (i.e. empty rangelist) */
760 {"", "", 0, { {0, 0, FALSE
}},
761 0, { {0, 0, FALSE
}}},
762 {"", "/A: 5-8,10-100", 0, { {0, 0, FALSE
}},
763 0, { {0, 0, FALSE
}}},
764 {"/A: 5-8,10-100", "", 2, { {4, 8, TRUE
}, {9, 100, TRUE
}},
765 2, { {4, 8, TRUE
}, {9, 100, TRUE
}}}
768 *msg
= "remove rangelists";
769 err
= child_err
= SVN_NO_ERROR
;
770 for (j
= 0; j
< 2; j
++)
772 for (i
= 0; i
< SIZE_OF_RANGE_REMOVE_TEST_ARRAY
; i
++)
774 int expected_nbr_ranges
;
775 svn_merge_range_t
*expected_ranges
;
777 SVN_ERR(svn_mergeinfo_parse(&info1
, (test_data
[i
]).eraser
, pool
));
778 SVN_ERR(svn_mergeinfo_parse(&info2
, (test_data
[i
]).whiteboard
, pool
));
779 eraser
= apr_hash_get(info1
, "/A", APR_HASH_KEY_STRING
);
780 whiteboard
= apr_hash_get(info2
, "/A", APR_HASH_KEY_STRING
);
782 /* Represent empty mergeinfo with an empty rangelist. */
784 eraser
= apr_array_make(pool
, 0, sizeof(*eraser
));
785 if (whiteboard
== NULL
)
786 whiteboard
= apr_array_make(pool
, 0, sizeof(*whiteboard
));
788 /* First pass try removal considering inheritance, on the
789 second pass ignore it. */
792 expected_nbr_ranges
= (test_data
[i
]).expected_ranges_consider_inheritance
;
793 expected_ranges
= (test_data
[i
]).expected_removed_consider_inheritance
;
798 expected_nbr_ranges
= (test_data
[i
]).expected_ranges_ignore_inheritance
;
799 expected_ranges
= (test_data
[i
]).expected_removed_ignore_inheritance
;
802 SVN_ERR(svn_rangelist_remove(&output
, eraser
, whiteboard
,
803 j
== 0 ? TRUE
: FALSE
,
805 child_err
= verify_ranges_match(output
, expected_ranges
,
808 "svn_rangelist_remove "
812 /* Collect all the errors rather than returning on the first. */
816 svn_error_compose(err
, child_err
);
825 /* ### Share code with test_diff_mergeinfo() and test_remove_rangelist(). */
827 test_remove_mergeinfo(const char **msg
,
828 svn_boolean_t msg_only
,
829 svn_test_opts_t
*opts
,
832 apr_hash_t
*output
, *whiteboard
, *eraser
;
833 svn_merge_range_t expected_rangelist_remainder
[NBR_RANGELIST_DELTAS
] =
834 { {6, 7, TRUE
}, {8, 9, TRUE
}, {10, 11, TRUE
}, {32, 34, TRUE
} };
836 *msg
= "remove of mergeinfo";
840 SVN_ERR(svn_mergeinfo_parse(&whiteboard
,
841 "/trunk: 1,3-4,7,9,11-12,31-34", pool
));
842 SVN_ERR(svn_mergeinfo_parse(&eraser
, "/trunk: 1-6,12-16,30-32", pool
));
844 /* Leftover on /trunk should be the set (7, 9, 11, 33-34) */
845 SVN_ERR(svn_mergeinfo_remove(&output
, eraser
, whiteboard
, pool
));
847 /* Verify calculation of range list remainder. */
848 return verify_mergeinfo_deltas(output
, expected_rangelist_remainder
,
849 "svn_mergeinfo_remove", "leftover", pool
);
851 #undef NBR_RANGELIST_DELTAS
854 test_rangelist_to_string(const char **msg
,
855 svn_boolean_t msg_only
,
856 svn_test_opts_t
*opts
,
859 apr_array_header_t
*result
;
860 svn_stringbuf_t
*output
;
861 svn_stringbuf_t
*expected
= svn_stringbuf_create("3,5,7-11,13-14", pool
);
863 *msg
= "turning rangelist back into a string";
868 SVN_ERR(svn_mergeinfo_parse(&info1
, mergeinfo1
, pool
));
870 result
= apr_hash_get(info1
, "/trunk", APR_HASH_KEY_STRING
);
872 return fail(pool
, "Missing path in parsed mergeinfo");
874 SVN_ERR(svn_rangelist_to_stringbuf(&output
, result
, pool
));
876 if (svn_stringbuf_compare(expected
, output
) != TRUE
)
877 return fail(pool
, "Rangelist string not what we expected");
883 test_mergeinfo_to_string(const char **msg
,
884 svn_boolean_t msg_only
,
885 svn_test_opts_t
*opts
,
888 svn_string_t
*output
;
889 svn_string_t
*expected
;
890 expected
= svn_string_create("/fred:8-10\n/trunk:3,5,7-11,13-14", pool
);
892 *msg
= "turning mergeinfo back into a string";
897 SVN_ERR(svn_mergeinfo_parse(&info1
, mergeinfo1
, pool
));
899 SVN_ERR(svn_mergeinfo__to_string(&output
, info1
, pool
));
901 if (svn_string_compare(expected
, output
) != TRUE
)
902 return fail(pool
, "Mergeinfo string not what we expected");
908 test_range_compact(const char **msg
,
909 svn_boolean_t msg_only
,
910 svn_test_opts_t
*opts
,
913 #define SIZE_OF_TEST_ARRAY 44
914 svn_merge_range_t rangelist
[SIZE_OF_TEST_ARRAY
][4] =
915 /* For each ith element of rangelist[][], try to combine/compact
916 rangelist[i][0] and rangelist[i][1]. If the combined ranges can
917 be combined, then the expected range is rangelist[i][2] and
918 rangelist[i][3] is {-1, -1, TRUE}. If the ranges cancel each
919 other out, then both rangelist[i][2] and rangelist[i][3] are
921 range1 + range2 = range3 , range4 */
922 { /* Non-intersecting ranges */
923 { { 2, 4, TRUE
}, { 6, 13, TRUE
}, { 2, 4, TRUE
}, { 6, 13, TRUE
} },
924 { { 4, 2, TRUE
}, { 6, 13, TRUE
}, { 4, 2, TRUE
}, { 6, 13, TRUE
} },
925 { { 4, 2, TRUE
}, {13, 6, TRUE
}, { 4, 2, TRUE
}, {13, 6, TRUE
} },
926 { { 2, 4, TRUE
}, {13, 6, TRUE
}, { 2, 4, TRUE
}, {13, 6, TRUE
} },
927 { { 6, 13, TRUE
}, { 2, 4, TRUE
}, { 6, 13, TRUE
}, { 2, 4, TRUE
} },
928 { { 6, 13, TRUE
}, { 4, 2, TRUE
}, { 6, 13, TRUE
}, { 4, 2, TRUE
} },
929 { {13, 6, TRUE
}, { 4, 2, TRUE
}, {13, 6, TRUE
}, { 4, 2, TRUE
} },
930 { {13, 6, TRUE
}, { 2, 4, TRUE
}, {13, 6, TRUE
}, { 2, 4, TRUE
} },
931 /* Intersecting ranges with no common start or end points */
932 { { 2, 5, TRUE
}, { 4, 6, TRUE
}, { 2, 6, TRUE
}, {-1, -1, TRUE
} },
933 { { 2, 5, TRUE
}, { 6, 4, TRUE
}, { 2, 4, TRUE
}, { 6, 5, TRUE
} },
934 { { 5, 2, TRUE
}, { 4, 6, TRUE
}, { 4, 2, TRUE
}, { 5, 6, TRUE
} },
935 { { 5, 2, TRUE
}, { 6, 4, TRUE
}, { 6, 2, TRUE
}, {-1, -1, TRUE
} },
936 { { 4, 6, TRUE
}, { 2, 5, TRUE
}, { 2, 6, TRUE
}, {-1, -1, TRUE
} },
937 { { 6, 4, TRUE
}, { 2, 5, TRUE
}, { 6, 5, TRUE
}, { 2, 4, TRUE
} },
938 { { 4, 6, TRUE
}, { 5, 2, TRUE
}, { 5, 6, TRUE
}, { 4, 2, TRUE
} },
939 { { 6, 4, TRUE
}, { 5, 2, TRUE
}, { 6, 2, TRUE
}, {-1, -1, TRUE
} },
940 /* One range is a proper subset of the other. */
941 { {33, 43, TRUE
}, {37, 38, TRUE
}, {33, 43, TRUE
}, {-1, -1, TRUE
} },
942 { {33, 43, TRUE
}, {38, 37, TRUE
}, {33, 37, TRUE
}, {38, 43, TRUE
} },
943 { {43, 33, TRUE
}, {37, 38, TRUE
}, {37, 33, TRUE
}, {43, 38, TRUE
} },
944 { {43, 33, TRUE
}, {38, 37, TRUE
}, {43, 33, TRUE
}, {-1, -1, TRUE
} },
945 { {37, 38, TRUE
}, {33, 43, TRUE
}, {33, 43, TRUE
}, {-1, -1, TRUE
} },
946 { {38, 37, TRUE
}, {33, 43, TRUE
}, {33, 37, TRUE
}, {38, 43, TRUE
} },
947 { {37, 38, TRUE
}, {43, 33, TRUE
}, {37, 33, TRUE
}, {43, 38, TRUE
} },
948 { {38, 37, TRUE
}, {43, 33, TRUE
}, {43, 33, TRUE
}, {-1, -1, TRUE
} },
949 /* Intersecting ranges share same start and end points */
950 { { 4, 20, TRUE
}, { 4, 20, TRUE
}, { 4, 20, TRUE
}, {-1, -1, TRUE
} },
951 { { 4, 20, TRUE
}, {20, 4, TRUE
}, {-1, -1, TRUE
}, {-1, -1, TRUE
} },
952 { {20, 4, TRUE
}, { 4, 20, TRUE
}, {-1, -1, TRUE
}, {-1, -1, TRUE
} },
953 { {20, 4, TRUE
}, {20, 4, TRUE
}, {20, 4, TRUE
}, {-1, -1, TRUE
} },
954 /* Intersecting ranges share same start point */
955 { { 7, 13, TRUE
}, { 7, 19, TRUE
}, { 7, 19, TRUE
}, {-1, -1, TRUE
} },
956 { { 7, 13, TRUE
}, {19, 7, TRUE
}, {19, 13, TRUE
}, {-1, -1, TRUE
} },
957 { {13, 7, TRUE
}, {7, 19, TRUE
}, {13, 19, TRUE
}, {-1, -1, TRUE
} },
958 { {13, 7, TRUE
}, {19, 7, TRUE
}, {19, 7, TRUE
}, {-1, -1, TRUE
} },
959 { { 7, 19, TRUE
}, { 7, 13, TRUE
}, { 7, 19, TRUE
}, {-1, -1, TRUE
} },
960 { {19, 7, TRUE
}, { 7, 13, TRUE
}, {19, 13, TRUE
}, {-1, -1, TRUE
} },
961 { { 7, 19, TRUE
}, {13, 7, TRUE
}, {13, 19, TRUE
}, {-1, -1, TRUE
} },
962 { {19, 7, TRUE
}, {13, 7, TRUE
}, {19, 7, TRUE
}, {-1, -1, TRUE
} },
963 /* Intersecting ranges share same end point */
964 { {12, 23, TRUE
}, {18, 23, TRUE
}, {12, 23, TRUE
}, {-1, -1, TRUE
} },
965 { {12, 23, TRUE
}, {23, 18, TRUE
}, {12, 18, TRUE
}, {-1, -1, TRUE
} },
966 { {23, 12, TRUE
}, {18, 23, TRUE
}, {18, 12, TRUE
}, {-1, -1, TRUE
} },
967 { {23, 12, TRUE
}, {23, 18, TRUE
}, {23, 12, TRUE
}, {-1, -1, TRUE
} },
968 { {18, 23, TRUE
}, {12, 23, TRUE
}, {12, 23, TRUE
}, {-1, -1, TRUE
} },
969 { {23, 18, TRUE
}, {12, 23, TRUE
}, {12, 18, TRUE
}, {-1, -1, TRUE
} },
970 { {18, 23, TRUE
}, {23, 12, TRUE
}, {18, 12, TRUE
}, {-1, -1, TRUE
} },
971 { {23, 18, TRUE
}, {23, 12, TRUE
}, {23, 12, TRUE
}, {-1, -1, TRUE
} } };
974 *msg
= "combination of ranges";
978 for (i
= 0; i
< SIZE_OF_TEST_ARRAY
; i
++)
980 svn_merge_range_t
*r1
= apr_palloc(pool
, sizeof(*r1
));
981 svn_merge_range_t
*r2
= apr_palloc(pool
, sizeof(*r2
));
982 svn_merge_range_t
*r1_expected
= &(rangelist
[i
][2]);
983 svn_merge_range_t
*r2_expected
= &(rangelist
[i
][3]);
985 r1
->start
= rangelist
[i
][0].start
;
986 r1
->end
= rangelist
[i
][0].end
;
987 r1
->inheritable
= TRUE
;
989 r2
->start
= rangelist
[i
][1].start
;
990 r2
->end
= rangelist
[i
][1].end
;
991 r2
->inheritable
= TRUE
;
993 svn_range_compact(&r1
, &r2
);
994 if (!(((!r1
&& r1_expected
->start
== -1
995 && r1_expected
->end
== -1)
996 || (r1
&& (r1
->start
== r1_expected
->start
997 && r1
->end
== r1_expected
->end
)))
998 && ((!r2
&& r2_expected
->start
== -1
999 && r2_expected
->end
== -1)
1000 || (r2
&& (r2
->start
== r2_expected
->start
1001 && r2
->end
== r2_expected
->end
)))))
1003 const char *fail_msg
= "svn_range_compact() should combine ranges ";
1004 fail_msg
= apr_pstrcat(pool
, fail_msg
,
1005 apr_psprintf(pool
, "(%ld-%ld),(%ld-%ld) "
1007 rangelist
[i
][0].start
,
1008 rangelist
[i
][0].end
,
1009 rangelist
[i
][1].start
,
1010 rangelist
[i
][1].end
), NULL
);
1011 if (r1_expected
->start
== -1)
1012 fail_msg
= apr_pstrcat(pool
, fail_msg
, "(NULL),",NULL
);
1014 fail_msg
= apr_pstrcat(pool
, fail_msg
,
1015 apr_psprintf(pool
, "(%ld-%ld),",
1017 r1_expected
->end
), NULL
);
1018 if (r2_expected
->start
== -1)
1019 fail_msg
= apr_pstrcat(pool
, fail_msg
, "(NULL) ",NULL
);
1021 fail_msg
= apr_pstrcat(pool
, fail_msg
,
1022 apr_psprintf(pool
, "(%ld-%ld) ",
1024 r2_expected
->end
), NULL
);
1025 fail_msg
= apr_pstrcat(pool
, fail_msg
, "but instead resulted in ",
1028 fail_msg
= apr_pstrcat(pool
, fail_msg
,
1029 apr_psprintf(pool
, "(%ld-%ld),",
1030 r1
->start
, r1
->end
), NULL
);
1032 fail_msg
= apr_pstrcat(pool
, fail_msg
, "(NULL),",NULL
);
1034 fail_msg
= apr_pstrcat(pool
, fail_msg
,
1035 apr_psprintf(pool
, "(%ld-%ld),",
1036 r2
->start
, r2
->end
), NULL
);
1038 fail_msg
= apr_pstrcat(pool
, fail_msg
, "(NULL)",NULL
);
1040 return fail(pool
, fail_msg
);
1043 return SVN_NO_ERROR
;
1046 static svn_error_t
*
1047 test_rangelist_merge(const char **msg
,
1048 svn_boolean_t msg_only
,
1049 svn_test_opts_t
*opts
,
1053 svn_error_t
*err
, *child_err
;
1054 apr_array_header_t
*rangelist1
, *rangelist2
;
1056 /* Struct for svn_rangelist_merge test data. Similar to
1057 mergeinfo_merge_test_data struct in svn_mergeinfo_merge() test. */
1058 struct rangelist_merge_test_data
1060 const char *mergeinfo1
;
1061 const char *mergeinfo2
;
1062 int expected_ranges
;
1063 svn_merge_range_t expected_merge
[6];
1066 #define SIZE_OF_RANGE_MERGE_TEST_ARRAY 52
1067 /* The actual test data. */
1068 struct rangelist_merge_test_data test_data
[SIZE_OF_RANGE_MERGE_TEST_ARRAY
] =
1070 /* Non-intersecting ranges */
1071 {"/A: 1-44", "/A: 70-101", 2, {{ 0, 44, TRUE
}, {69, 101, TRUE
}}},
1072 {"/A: 1-44*", "/A: 70-101", 2, {{ 0, 44, FALSE
}, {69, 101, TRUE
}}},
1073 {"/A: 1-44", "/A: 70-101*", 2, {{ 0, 44, TRUE
}, {69, 101, FALSE
}}},
1074 {"/A: 1-44*", "/A: 70-101*", 2, {{ 0, 44, FALSE
}, {69, 101, FALSE
}}},
1075 {"/A: 70-101", "/A: 1-44", 2, {{ 0, 44, TRUE
}, {69, 101, TRUE
}}},
1076 {"/A: 70-101*", "/A: 1-44", 2, {{ 0, 44, TRUE
}, {69, 101, FALSE
}}},
1077 {"/A: 70-101", "/A: 1-44*", 2, {{ 0, 44, FALSE
}, {69, 101, TRUE
}}},
1078 {"/A: 70-101*", "/A: 1-44*", 2, {{ 0, 44, FALSE
}, {69, 101, FALSE
}}},
1080 /* Intersecting ranges with same starting and ending revisions */
1081 {"/A: 4-20", "/A: 4-20", 1, {{3, 20, TRUE
}}},
1082 {"/A: 4-20*", "/A: 4-20", 1, {{3, 20, TRUE
}}},
1083 {"/A: 4-20", "/A: 4-20*", 1, {{3, 20, TRUE
}}},
1084 {"/A: 4-20*", "/A: 4-20*", 1, {{3, 20, FALSE
}}},
1086 /* Intersecting ranges with same starting revision */
1087 {"/A: 6-17", "/A: 6-12", 1, {{5, 17, TRUE
}}},
1088 {"/A: 6-17*", "/A: 6-12", 2, {{5, 12, TRUE
}, {12, 17, FALSE
}}},
1089 {"/A: 6-17", "/A: 6-12*", 1, {{5, 17, TRUE
}}},
1090 {"/A: 6-17*", "/A: 6-12*", 1, {{5, 17, FALSE
}}},
1091 {"/A: 6-12", "/A: 6-17", 1, {{5, 17, TRUE
}}},
1092 {"/A: 6-12*", "/A: 6-17", 1, {{5, 17, TRUE
}}},
1093 {"/A: 6-12", "/A: 6-17*", 2, {{5, 12, TRUE
}, {12, 17, FALSE
}}},
1094 {"/A: 6-12*", "/A: 6-17*", 1, {{5, 17, FALSE
}}},
1096 /* Intersecting ranges with same ending revision */
1097 {"/A: 5-77", "/A: 44-77", 1, {{4, 77, TRUE
}}},
1098 {"/A: 5-77*", "/A: 44-77", 2, {{4, 43, FALSE
}, {43, 77, TRUE
}}},
1099 {"/A: 5-77", "/A: 44-77*", 1, {{4, 77, TRUE
}}},
1100 {"/A: 5-77*", "/A: 44-77*", 1, {{4, 77, FALSE
}}},
1101 {"/A: 44-77", "/A: 5-77", 1, {{4, 77, TRUE
}}},
1102 {"/A: 44-77*", "/A: 5-77", 1, {{4, 77, TRUE
}}},
1103 {"/A: 44-77", "/A: 5-77*", 2, {{4, 43, FALSE
}, {43, 77, TRUE
}}},
1104 {"/A: 44-77*", "/A: 5-77*", 1, {{4, 77, FALSE
}}},
1106 /* Intersecting ranges with different starting and ending revision
1107 where one range is a proper subset of the other. */
1108 {"/A: 12-24", "/A: 20-23", 1, {{11, 24, TRUE
}}},
1109 {"/A: 12-24*", "/A: 20-23", 3, {{11, 19, FALSE
}, {19, 23, TRUE
},
1111 {"/A: 12-24", "/A: 20-23*", 1, {{11, 24, TRUE
}}},
1112 {"/A: 12-24*", "/A: 20-23*", 1, {{11, 24, FALSE
}}},
1113 {"/A: 20-23", "/A: 12-24", 1, {{11, 24, TRUE
}}},
1114 {"/A: 20-23*", "/A: 12-24", 1, {{11, 24, TRUE
}}},
1115 {"/A: 20-23", "/A: 12-24*", 3, {{11, 19, FALSE
}, {19, 23, TRUE
},
1117 {"/A: 20-23*", "/A: 12-24*", 1, {{11, 24, FALSE
}}},
1119 /* Intersecting ranges with different starting and ending revision
1120 where neither range is a proper subset of the other. */
1121 {"/A: 50-73", "/A: 60-99", 1, {{49, 99, TRUE
}}},
1122 {"/A: 50-73*", "/A: 60-99", 2, {{49, 59, FALSE
}, {59, 99, TRUE
}}},
1123 {"/A: 50-73", "/A: 60-99*", 2, {{49, 73, TRUE
}, {73, 99, FALSE
}}},
1124 {"/A: 50-73*", "/A: 60-99*", 1, {{49, 99, FALSE
}}},
1125 {"/A: 60-99", "/A: 50-73", 1, {{49, 99, TRUE
}}},
1126 {"/A: 60-99*", "/A: 50-73", 2, {{49, 73, TRUE
}, {73, 99, FALSE
}}},
1127 {"/A: 60-99", "/A: 50-73*", 2, {{49, 59, FALSE
}, {59, 99, TRUE
}}},
1128 {"/A: 60-99*", "/A: 50-73*", 1, {{49, 99, FALSE
}}},
1130 /* Multiple ranges. */
1131 {"/A: 1-5,7,12-13", "/A: 2-17", 1, {{0, 17, TRUE
}}},
1132 {"/A: 1-5*,7*,12-13*", "/A: 2-17*", 1, {{0, 17, FALSE
}}},
1134 {"/A: 1-5,7,12-13", "/A: 2-17*", 6,
1135 {{0, 5, TRUE
}, { 5, 6, FALSE
}, { 6, 7, TRUE
},
1136 {7, 11, FALSE
}, {11, 13, TRUE
}, {13, 17, FALSE
}}},
1138 {"/A: 1-5*,7*,12-13*", "/A: 2-17", 2,
1139 {{0, 1, FALSE
}, {1, 17, TRUE
}}},
1141 {"/A: 2-17", "/A: 1-5,7,12-13", 1, {{0, 17, TRUE
}}},
1142 {"/A: 2-17*", "/A: 1-5*,7*,12-13*", 1, {{0, 17, FALSE
}}},
1144 {"/A: 2-17*", "/A: 1-5,7,12-13", 6,
1145 {{0, 5, TRUE
}, { 5, 6, FALSE
}, { 6, 7, TRUE
},
1146 {7, 11, FALSE
}, {11, 13, TRUE
}, {13, 17, FALSE
}}},
1148 {"/A: 2-17", "/A: 1-5*,7*,12-13*", 2,
1149 {{0, 1, FALSE
}, {1, 17, TRUE
}}},
1151 *msg
= "merge of rangelists";
1153 return SVN_NO_ERROR
;
1155 err
= child_err
= SVN_NO_ERROR
;
1156 for (i
= 0; i
< SIZE_OF_RANGE_MERGE_TEST_ARRAY
; i
++)
1158 SVN_ERR(svn_mergeinfo_parse(&info1
, (test_data
[i
]).mergeinfo1
, pool
));
1159 SVN_ERR(svn_mergeinfo_parse(&info2
, (test_data
[i
]).mergeinfo2
, pool
));
1160 rangelist1
= apr_hash_get(info1
, "/A", APR_HASH_KEY_STRING
);
1161 rangelist2
= apr_hash_get(info2
, "/A", APR_HASH_KEY_STRING
);
1162 SVN_ERR(svn_rangelist_merge(&rangelist1
, rangelist2
, pool
));
1163 child_err
= verify_ranges_match(rangelist1
,
1164 (test_data
[i
]).expected_merge
,
1165 (test_data
[i
]).expected_ranges
,
1167 "svn_rangelist_merge "
1171 /* Collect all the errors rather than returning on the first. */
1175 svn_error_compose(err
, child_err
);
1183 static svn_error_t
*
1184 test_rangelist_diff(const char **msg
,
1185 svn_boolean_t msg_only
,
1186 svn_test_opts_t
*opts
,
1190 svn_error_t
*err
, *child_err
;
1191 apr_array_header_t
*from
, *to
, *added
, *deleted
;
1193 /* Structure containing two ranges to diff and the expected output of the
1194 diff both when considering and ignoring range inheritance. */
1195 struct rangelist_diff_test_data
1197 /* svn:mergeinfo string representations */
1201 /* Expected results for performing svn_rangelist_diff
1202 while considering differences in inheritability to be real
1204 int expected_add_ranges
;
1205 svn_merge_range_t expected_adds
[10];
1206 int expected_del_ranges
;
1207 svn_merge_range_t expected_dels
[10];
1209 /* Expected results for performing svn_rangelist_diff
1210 while ignoring differences in inheritability. */
1211 int expected_add_ranges_ignore_inheritance
;
1212 svn_merge_range_t expected_adds_ignore_inheritance
[10];
1213 int expected_del_ranges_ignore_inheritance
;
1214 svn_merge_range_t expected_dels_ignore_inheritance
[10];
1217 #define SIZE_OF_RANGE_DIFF_TEST_ARRAY 16
1218 /* The actual test data array.
1220 'from' --> {"/A: 1,5-8", "/A: 1,6,10-12", <-- 'to'
1221 Number of adds when --> 1, { { 9, 12, TRUE } },
1222 considering inheritance
1224 Number of dels when --> 2, { { 4, 5, TRUE }, { 6, 8, TRUE } },
1225 considering inheritance
1227 Number of adds when --> 1, { { 9, 12, TRUE } },
1228 ignoring inheritance
1230 Number of dels when --> 2, { { 4, 5, TRUE }, { 6, 8, TRUE } } },
1231 ignoring inheritance
1233 The expected svn_merge_range_t's
1235 struct rangelist_diff_test_data test_data
[SIZE_OF_RANGE_DIFF_TEST_ARRAY
] =
1237 /* Add and Delete */
1239 1, { { 2, 3, TRUE
} },
1240 1, { { 0, 1, TRUE
} },
1241 1, { { 2, 3, TRUE
} },
1242 1, { { 0, 1, TRUE
} } },
1245 {"/A: 1", "/A: 1,3",
1246 1, { { 2, 3, TRUE
} },
1247 0, { { 0, 0, FALSE
} },
1248 1, { { 2, 3, TRUE
} },
1249 0, { { 0, 0, FALSE
} } },
1252 {"/A: 1,3", "/A: 1",
1253 0, { { 0, 0, FALSE
} },
1254 1, { { 2, 3, TRUE
} },
1255 0, { { 0, 0, FALSE
} },
1256 1, { { 2, 3, TRUE
} } },
1259 {"/A: 1,3", "/A: 1,3",
1260 0, { { 0, 0, FALSE
} },
1261 0, { { 0, 0, FALSE
} },
1262 0, { { 0, 0, FALSE
} },
1263 0, { { 0, 0, FALSE
} } },
1265 {"/A: 1,3*", "/A: 1,3*",
1266 0, { { 0, 0, FALSE
} },
1267 0, { { 0, 0, FALSE
} },
1268 0, { { 0, 0, FALSE
} },
1269 0, { { 0, 0, FALSE
} } },
1271 /* Adds and Deletes */
1272 {"/A: 1,5-8", "/A: 1,6,10-12",
1273 1, { { 9, 12, TRUE
} },
1274 2, { { 4, 5, TRUE
}, { 6, 8, TRUE
} },
1275 1, { { 9, 12, TRUE
} },
1276 2, { { 4, 5, TRUE
}, { 6, 8, TRUE
} } },
1279 1, { { 5, 6, TRUE
} },
1280 1, { { 5, 6, FALSE
} },
1281 0, { { 0, 0, FALSE
} },
1282 0, { { 0, 0, FALSE
} } },
1284 /* Intersecting range with different inheritability */
1286 1, { { 5, 6, FALSE
} },
1287 1, { { 5, 6, TRUE
} },
1288 0, { { 0, 0, FALSE
} },
1289 0, { { 0, 0, FALSE
} } },
1292 1, { { 5, 6, TRUE
} },
1293 1, { { 5, 6, FALSE
} },
1294 0, { { 0, 0, FALSE
} },
1295 0, { { 0, 0, FALSE
} } },
1297 {"/A: 1,5-8", "/A: 1,6*,10-12",
1298 2, { { 5, 6, FALSE
}, { 9, 12, TRUE
} },
1299 1, { { 4, 8, TRUE
} },
1300 1, { { 9, 12, TRUE
} },
1301 2, { { 4, 5, TRUE
}, { 6, 8, TRUE
} } },
1303 {"/A: 1,5-8*", "/A: 1,6,10-12",
1304 2, { { 5, 6, TRUE
}, { 9, 12, TRUE
} },
1305 1, { { 4, 8, FALSE
} },
1306 1, { { 9, 12, TRUE
} },
1307 2, { { 4, 5, FALSE
}, { 6, 8, FALSE
} } },
1309 /* Empty range diffs */
1311 0, { { 0, 0, FALSE
} },
1312 1, { { 2, 9, TRUE
} },
1313 0, { { 0, 0, FALSE
} },
1314 1, { { 2, 9, TRUE
} } },
1317 0, { { 0, 0, FALSE
} },
1318 1, { { 2, 9, FALSE
} },
1319 0, { { 0, 0, FALSE
} },
1320 1, { { 2, 9, FALSE
} } },
1323 1, { { 2, 9, TRUE
} },
1324 0, { { 0, 0, FALSE
} },
1325 1, { { 2, 9, TRUE
} },
1326 0, { { 0, 0, FALSE
} } },
1329 1, { { 2, 9, FALSE
} },
1330 0, { { 0, 0, FALSE
} },
1331 1, { { 2, 9, FALSE
} },
1332 0, { { 0, 0, FALSE
} } },
1334 /* Empty range no diff */
1336 0, { { 0, 0, FALSE
} },
1337 0, { { 0, 0, FALSE
} },
1338 0, { { 0, 0, FALSE
} },
1339 0, { { 0, 0, FALSE
} } },
1342 *msg
= "diff of rangelists";
1344 return SVN_NO_ERROR
;
1346 err
= child_err
= SVN_NO_ERROR
;
1347 for (i
= 0; i
< SIZE_OF_RANGE_DIFF_TEST_ARRAY
; i
++)
1349 SVN_ERR(svn_mergeinfo_parse(&info1
, (test_data
[i
]).to
, pool
));
1350 SVN_ERR(svn_mergeinfo_parse(&info2
, (test_data
[i
]).from
, pool
));
1351 to
= apr_hash_get(info1
, "/A", APR_HASH_KEY_STRING
);
1352 from
= apr_hash_get(info2
, "/A", APR_HASH_KEY_STRING
);
1354 /* Represent empty mergeinfo with an empty rangelist. */
1356 to
= apr_array_make(pool
, 0, sizeof(*to
));
1358 from
= apr_array_make(pool
, 0, sizeof(*from
));
1360 /* First diff the ranges while considering
1361 differences in inheritance. */
1362 SVN_ERR(svn_rangelist_diff(&deleted
, &added
, from
, to
, TRUE
, pool
));
1364 child_err
= verify_ranges_match(added
,
1365 (test_data
[i
]).expected_adds
,
1366 (test_data
[i
]).expected_add_ranges
,
1368 "svn_rangelist_diff"
1372 child_err
= verify_ranges_match(deleted
,
1373 (test_data
[i
]).expected_dels
,
1374 (test_data
[i
]).expected_del_ranges
,
1376 "svn_rangelist_diff"
1381 /* Now do the diff while ignoring differences in inheritance. */
1382 SVN_ERR(svn_rangelist_diff(&deleted
, &added
, from
, to
, FALSE
,
1384 child_err
= verify_ranges_match(
1386 (test_data
[i
]).expected_adds_ignore_inheritance
,
1387 (test_data
[i
]).expected_add_ranges_ignore_inheritance
,
1388 apr_psprintf(pool
, "svn_rangelist_diff case %i", i
),
1392 child_err
= verify_ranges_match(
1394 (test_data
[i
]).expected_dels_ignore_inheritance
,
1395 (test_data
[i
]).expected_del_ranges_ignore_inheritance
,
1396 apr_psprintf(pool
, "svn_rangelist_diff case %i", i
),
1400 /* Collect all the errors rather than returning on the first. */
1404 svn_error_compose(err
, child_err
);
1412 /* The test table. */
1414 struct svn_test_descriptor_t test_funcs
[] =
1417 SVN_TEST_PASS(test_parse_single_line_mergeinfo
),
1418 SVN_TEST_PASS(test_mergeinfo_dup
),
1419 SVN_TEST_PASS(test_parse_combine_rangeinfo
),
1420 SVN_TEST_PASS(test_parse_broken_mergeinfo
),
1421 SVN_TEST_PASS(test_remove_rangelist
),
1422 SVN_TEST_PASS(test_remove_mergeinfo
),
1423 SVN_TEST_PASS(test_rangelist_reverse
),
1424 SVN_TEST_PASS(test_rangelist_count_revs
),
1425 SVN_TEST_PASS(test_rangelist_to_revs
),
1426 SVN_TEST_PASS(test_rangelist_intersect
),
1427 SVN_TEST_PASS(test_diff_mergeinfo
),
1428 SVN_TEST_PASS(test_merge_mergeinfo
),
1429 SVN_TEST_PASS(test_rangelist_to_string
),
1430 SVN_TEST_PASS(test_mergeinfo_to_string
),
1431 SVN_TEST_PASS(test_range_compact
),
1432 SVN_TEST_PASS(test_rangelist_merge
),
1433 SVN_TEST_PASS(test_rangelist_diff
),